<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
<meta name="viewport" content="width=device-width">
<meta name="theme-color" content="#222"><meta name="generator" content="Hexo 7.3.0">

  <link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-next.png">
  <link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32.ico">
  <link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16.ico">
  <link rel="mask-icon" href="/images/logo.svg" color="#222">

<link rel="stylesheet" href="/css/main.css">



<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css" integrity="sha256-wiz7ZSCn/btzhjKDQBms9Hx4sSeUYsDrTLg7roPstac=" crossorigin="anonymous">
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.1.1/animate.min.css" integrity="sha256-PR7ttpcvz8qrF57fur/yAx1qXMFJeJFiA6pSzWi0OIE=" crossorigin="anonymous">
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/fancyapps-ui/5.0.28/fancybox/fancybox.css" integrity="sha256-6cQIC71/iBIYXFK+0RHAvwmjwWzkWd+r7v/BX3/vZDc=" crossorigin="anonymous">
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/pace/1.2.4/themes/green/pace-theme-minimal.css">
  <script src="https://cdnjs.cloudflare.com/ajax/libs/pace/1.2.4/pace.min.js" integrity="sha256-gqd7YTjg/BtfqWSwsJOvndl0Bxc8gFImLEkXQT8+qj0=" crossorigin="anonymous"></script>

<script class="next-config" data-name="main" type="application/json">{"hostname":"sumumm.github.io","root":"/","images":"/images","scheme":"Gemini","darkmode":false,"version":"8.19.2","exturl":false,"sidebar":{"position":"left","display":"post","padding":18,"offset":12},"copycode":{"enable":true,"style":"mac"},"fold":{"enable":true,"height":300},"bookmark":{"enable":false,"color":"#222","save":"auto"},"mediumzoom":false,"lazyload":true,"pangu":false,"comments":{"style":"tabs","active":null,"storage":true,"lazyload":false,"nav":null},"stickytabs":false,"motion":{"enable":true,"async":true,"transition":{"menu_item":"fadeInDown","post_block":"fadeIn","post_header":"fadeInDown","post_body":"fadeInDown","coll_header":"fadeInLeft","sidebar":"fadeInUp"}},"i18n":{"placeholder":"搜索...","empty":"没有找到任何搜索结果：${query}","hits_time":"找到 ${hits} 个搜索结果（用时 ${time} 毫秒）","hits":"找到 ${hits} 个搜索结果"},"path":"/search.xml","localsearch":{"enable":true,"trigger":"auto","top_n_per_article":1,"unescape":false,"preload":false}}</script><script src="/js/config.js"></script>

    <meta name="description" content="本文主要是kernel——顶层Makefile基础解析的相关笔记，若笔记中有错误或者不合适的地方，欢迎批评指正😃。">
<meta property="og:type" content="article">
<meta property="og:title" content="LV05-03-Kernel-03-01-顶层Makefile基础解析">
<meta property="og:url" content="https://sumumm.github.io/post/2aa70834.html">
<meta property="og:site_name" content="苏木">
<meta property="og:description" content="本文主要是kernel——顶层Makefile基础解析的相关笔记，若笔记中有错误或者不合适的地方，欢迎批评指正😃。">
<meta property="og:locale" content="zh_CN">
<meta property="article:published_time" content="2024-11-26T23:53:43.000Z">
<meta property="article:modified_time" content="2025-06-13T16:25:57.044Z">
<meta property="article:author" content="苏木">
<meta property="article:tag" content="LV05-系统镜像">
<meta name="twitter:card" content="summary">


<link rel="canonical" href="https://sumumm.github.io/post/2aa70834.html">



<script class="next-config" data-name="page" type="application/json">{"sidebar":"","isHome":false,"isPost":true,"lang":"zh-CN","comments":"","permalink":"https://sumumm.github.io/post/2aa70834.html","path":"post/2aa70834.html","title":"LV05-03-Kernel-03-01-顶层Makefile基础解析"}</script>

<script class="next-config" data-name="calendar" type="application/json">""</script>
<title>LV05-03-Kernel-03-01-顶层Makefile基础解析 | 苏木</title>
  








    <script src="/js/browser_tools_disable.js"></script>

  <noscript>
    <link rel="stylesheet" href="/css/noscript.css">
  </noscript>
<!-- hexo injector head_end start --><link rel="stylesheet" href="https://unpkg.com/hexo-next-tags-plus@latest/lib/tag_plus.css" media="defer" onload="this.media='all'"><!-- hexo injector head_end end --></head>

<body itemscope itemtype="http://schema.org/WebPage" class="use-motion">
  <div class="headband"></div>

  <main class="main">
    <div class="column">
      <header class="header" itemscope itemtype="http://schema.org/WPHeader"><div class="site-brand-container">
  <div class="site-nav-toggle">
    <div class="toggle" aria-label="切换导航栏" role="button">
        <span class="toggle-line"></span>
        <span class="toggle-line"></span>
        <span class="toggle-line"></span>
    </div>
  </div>

  <div class="site-meta">

    <a href="/" class="brand" rel="start">
      <i class="logo-line"></i>
      <p class="site-title">苏木</p>
      <i class="logo-line"></i>
    </a>
      <p class="site-subtitle" itemprop="description">我的学习之路</p>
  </div>

  <div class="site-nav-right">
    <div class="toggle popup-trigger" aria-label="搜索" role="button">
        <i class="fa fa-search fa-fw fa-lg"></i>
    </div>
  </div>
</div>



<nav class="site-nav">
  <ul class="main-menu menu"><li class="menu-item menu-item-home"><a href="/" rel="section"><i class="fa fa-home fa-fw"></i>苏木的家</a></li><li class="menu-item menu-item-categories"><a href="/categories/" rel="section"><i class="fa fa-th fa-fw"></i>分类页<span class="badge">42</span></a></li><li class="menu-item menu-item-archives"><a href="/archives/" rel="section"><i class="fa fa-archive fa-fw"></i>归档页<span class="badge">673</span></a></li><li class="menu-item menu-item-flink"><a href="/flink/" rel="section"><i class="fa fa-link fa-fw"></i>友人帐</a></li><li class="menu-item menu-item-about"><a href="/about/" rel="section"><i class="fa fa-user fa-fw"></i>关于我</a></li>
      <li class="menu-item menu-item-search">
        <a role="button" class="popup-trigger"><i class="fa fa-search fa-fw"></i>搜索
        </a>
      </li>
  </ul>
</nav>



  <div class="search-pop-overlay">
    <div class="popup search-popup"><div class="search-header">
  <span class="search-icon">
    <i class="fa fa-search"></i>
  </span>
  <div class="search-input-container">
    <input autocomplete="off" autocapitalize="off" maxlength="80"
           placeholder="搜索..." spellcheck="false"
           type="search" class="search-input">
  </div>
  <span class="popup-btn-close" role="button">
    <i class="fa fa-times-circle"></i>
  </span>
</div>
<div class="search-result-container no-result">
  <div class="search-result-icon">
    <i class="fa fa-spinner fa-pulse fa-5x"></i>
  </div>
</div>

    </div>
  </div>

</header>
        
  
  <aside class="sidebar">

    <div class="sidebar-inner sidebar-nav-active sidebar-toc-active">
      <ul class="sidebar-nav">
        <li class="sidebar-nav-toc">
          文章目录
        </li>
        <li class="sidebar-nav-overview">
          站点概览
        </li>
      </ul>

      <div class="sidebar-panel-container">
        <!--noindex-->
        <div class="post-toc-wrap sidebar-panel">
            <div class="post-toc animated"><ol class="nav"><li class="nav-item nav-level-1"><a class="nav-link" href="#%E4%B8%80%E3%80%81%E6%A6%82%E8%BF%B0"><span class="nav-text">一、概述</span></a></li><li class="nav-item nav-level-1"><a class="nav-link" href="#%E4%BA%8C%E3%80%81make-xxx-defconfig"><span class="nav-text">二、make xxx_defconfig</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#1-%E6%89%93%E5%8D%B0%E4%BF%A1%E6%81%AF"><span class="nav-text">1. 打印信息</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#2-config%E7%9B%AE%E6%A0%87"><span class="nav-text">2. %config目标</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#3-build%E5%8F%98%E9%87%8F"><span class="nav-text">3. build变量</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#4-scripts-basic"><span class="nav-text">4. scripts_basic</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#5-Makefile-build"><span class="nav-text">5. Makefile.build</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#5-1-scripts-basic-%E7%9B%AE%E6%A0%87%E5%AF%B9%E5%BA%94%E7%9A%84%E5%91%BD%E4%BB%A4"><span class="nav-text">5.1 scripts_basic 目标对应的命令</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#5-2-config-%E7%9B%AE%E6%A0%87%E5%AF%B9%E5%BA%94%E7%9A%84%E5%91%BD%E4%BB%A4"><span class="nav-text">5.2 %config 目标对应的命令</span></a></li></ol></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#%E4%B8%89%E3%80%81make-all"><span class="nav-text">三、make all</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#1-all%E7%9B%AE%E6%A0%87"><span class="nav-text">1. _all目标</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#2-all%E7%9B%AE%E6%A0%87"><span class="nav-text">2. all目标</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#3-vmlinux%E7%9B%AE%E6%A0%87"><span class="nav-text">3. vmlinux目标</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#3-1-vmlinux%E7%AE%80%E5%8D%95%E5%B1%95%E5%BC%80"><span class="nav-text">3.1 vmlinux简单展开</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#3-2-%E4%BE%9D%E8%B5%96%E7%9A%84%E5%8F%98%E9%87%8F"><span class="nav-text">3.2 依赖的变量</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#3-2-1-head-y"><span class="nav-text">3.2.1 head-y</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#3-2-2-init-y%E3%80%81drivers-y-%E5%92%8C-net-y"><span class="nav-text">3.2.2 init-y、drivers-y 和 net-y</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#3-2-3-libs-y1%E5%92%8Clibs-y2"><span class="nav-text">3.2.3 libs-y1和libs-y2</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#3-2-4-core-y"><span class="nav-text">3.2.4 core-y</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#3-2-5-%E6%80%BB%E7%BB%93"><span class="nav-text">3.2.5 总结</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#3-3-if-changed%E5%87%BD%E6%95%B0"><span class="nav-text">3.3 if_changed函数</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#3-3-1-any-prereq"><span class="nav-text">3.3.1 any-prereq</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#3-3-2-arg-check"><span class="nav-text">3.3.2 arg-check</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#3-3-3-cmd-1"><span class="nav-text">3.3.3 cmd_$(1)</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#3-3-4-link-vmlinux-sh"><span class="nav-text">3.3.4 link-vmlinux.sh</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#3-4-%E6%89%93%E5%8D%B0%E4%BF%A1%E6%81%AF"><span class="nav-text">3.4 打印信息</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#4-built-in-a%E7%94%9F%E6%88%90%E8%BF%87%E7%A8%8B"><span class="nav-text">4. built-in.a生成过程</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#4-1-vmlinux-deps%E5%8F%98%E9%87%8F"><span class="nav-text">4.1 vmlinux-deps变量</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#4-2-vmlinux-deps%E7%9A%84%E4%BE%9D%E8%B5%96"><span class="nav-text">4.2 vmlinux-deps的依赖</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#4-3-vmlinux-dirs%E5%8F%98%E9%87%8F"><span class="nav-text">4.3 vmlinux-dirs变量</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#4-4-vmlinux-dirs%E7%9A%84%E4%BE%9D%E8%B5%96"><span class="nav-text">4.4 vmlinux-dirs的依赖</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#4-4-1-%E8%A7%84%E5%88%99%E5%B1%95%E5%BC%80"><span class="nav-text">4.4.1 规则展开</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#4-4-2-%E5%91%BD%E4%BB%A4%E5%88%86%E6%9E%90"><span class="nav-text">4.4.2 命令分析</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#4-5-%E6%89%93%E5%8D%B0%E4%BF%A1%E6%81%AF"><span class="nav-text">4.5 打印信息</span></a></li></ol></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#%E5%9B%9B%E3%80%81make-zImage"><span class="nav-text">四、make zImage</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#1-vmlinux%E3%80%81-Image%EF%BC%8C-zImage%E3%80%81-uImage-%E7%9A%84%E5%8C%BA%E5%88%AB"><span class="nav-text">1. vmlinux、 Image， zImage、 uImage 的区别  </span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#2-zImage"><span class="nav-text">2. zImage</span></a></li></ol></li></ol></div>
        </div>
        <!--/noindex-->

        <div class="site-overview-wrap sidebar-panel">
          <div class="site-author animated" itemprop="author" itemscope itemtype="http://schema.org/Person">
    <img class="site-author-image" itemprop="image" alt="苏木"
      src="/images/avatar.jpg">
  <p class="site-author-name" itemprop="name">苏木</p>
  <div class="site-description" itemprop="description">莫道桑榆晚，为霞尚满天</div>
</div>
<div class="site-state-wrap animated">
  <nav class="site-state">
      <div class="site-state-item site-state-posts">
        <a href="/archives/">
          <span class="site-state-item-count">673</span>
          <span class="site-state-item-name">日志</span>
        </a>
      </div>
      <div class="site-state-item site-state-categories">
          <a href="/categories/">
        <span class="site-state-item-count">42</span>
        <span class="site-state-item-name">分类</span></a>
      </div>
      <div class="site-state-item site-state-tags">
        <span class="site-state-item-count">43</span>
        <span class="site-state-item-name">标签</span>
      </div>
  </nav>
</div>
  <div class="links-of-author animated">
      <span class="links-of-author-item">
        <a href="https://github.com/sumumm" title="GitHub → https:&#x2F;&#x2F;github.com&#x2F;sumumm" rel="noopener me" target="_blank"><i class="fab fa-github fa-fw"></i>GitHub</a>
      </span>
  </div>

        </div>
      </div>
    </div>

    
  </aside>


    </div>

    <div class="main-inner post posts-expand">


  


<div class="post-block">
  
  

  <article itemscope itemtype="http://schema.org/Article" class="post-content" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="https://sumumm.github.io/post/2aa70834.html">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.jpg">
      <meta itemprop="name" content="苏木">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="苏木">
      <meta itemprop="description" content="莫道桑榆晚，为霞尚满天">
    </span>

    <span hidden itemprop="post" itemscope itemtype="http://schema.org/CreativeWork">
      <meta itemprop="name" content="LV05-03-Kernel-03-01-顶层Makefile基础解析 | 苏木">
      <meta itemprop="description" content="">
    </span>
      <header class="post-header">
        <h1 class="post-title" itemprop="name headline">
          LV05-03-Kernel-03-01-顶层Makefile基础解析
        </h1>

        <div class="post-meta-container">
          <div class="post-meta">
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar"></i>
      </span>
      <span class="post-meta-item-text">发表于</span>

      <time title="创建时间：2024-11-27 07:53:43" itemprop="dateCreated datePublished" datetime="2024-11-27T07:53:43+08:00">2024-11-27</time>
    </span>
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-folder"></i>
      </span>
      <span class="post-meta-item-text">分类于</span>
        <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
          <a href="/categories/%E5%B5%8C%E5%85%A5%E5%BC%8F%E5%BC%80%E5%8F%91/" itemprop="url" rel="index"><span itemprop="name">嵌入式开发</span></a>
        </span>
          ，
        <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
          <a href="/categories/%E5%B5%8C%E5%85%A5%E5%BC%8F%E5%BC%80%E5%8F%91/02IMX6ULL%E5%B9%B3%E5%8F%B0/" itemprop="url" rel="index"><span itemprop="name">02IMX6ULL平台</span></a>
        </span>
          ，
        <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
          <a href="/categories/%E5%B5%8C%E5%85%A5%E5%BC%8F%E5%BC%80%E5%8F%91/02IMX6ULL%E5%B9%B3%E5%8F%B0/LV05-%E7%B3%BB%E7%BB%9F%E9%95%9C%E5%83%8F/" itemprop="url" rel="index"><span itemprop="name">LV05-系统镜像</span></a>
        </span>
    </span>

  
    <span class="post-meta-break"></span>
    <span class="post-meta-item" title="本文字数">
      <span class="post-meta-item-icon">
        <i class="far fa-file-word"></i>
      </span>
      <span class="post-meta-item-text">本文字数：</span>
      <span>8k</span>
    </span>
    <span class="post-meta-item" title="阅读时长">
      <span class="post-meta-item-icon">
        <i class="far fa-clock"></i>
      </span>
      <span class="post-meta-item-text">阅读时长 &asymp;</span>
      <span>29 分钟</span>
    </span>
</div>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody"><p>本文主要是kernel——顶层Makefile基础解析的相关笔记，若笔记中有错误或者不合适的地方，欢迎批评指正😃。</p>
<span id="more"></span>

<!-- Photo: https://fanhua-picture.oss-cn-hangzhou.aliyuncs.com/01%E5%B5%8C%E5%85%A5%E5%BC%8F%E5%BC%80%E5%8F%91/02IMX6ULL%E5%B9%B3%E5%8F%B0/LV05-%E7%B3%BB%E7%BB%9F%E9%95%9C%E5%83%8F/LV05-03-Kernel-03-01-%E9%A1%B6%E5%B1%82Makefile%E5%9F%BA%E7%A1%80%E8%A7%A3%E6%9E%90/img/ -->

<details class="folding-tag" blue><summary> 点击查看使用工具及版本 </summary>
              <div class='content'>
              <table>    <tr>        <td align="center" rowspan="5">PC端开发环境</td>        <td align="center" width=150px>Windows</td>        <td align="left">Windows11</td>    </tr>    <tr>        <td align="center">Ubuntu</td>        <td align="left">Ubuntu20.04.2的64位版本</td>      </tr>    <tr>        <td align="center">VMware® Workstation 17 Pro</td>        <td align="left">17.6.0 build-24238078</td>      </tr>    <tr>        <td align="center">终端软件</td>        <td align="left">MobaXterm(Professional Edition v23.0 Build 5042 (license))</td>    </tr>    <tr>        <td align="center">Win32DiskImager</td>        <td align="left">Win32DiskImager v1.0</td>      </tr>    <tr>        <td align="center" rowspan="3">Linux开发板环境</td>        <td align="center">Linux开发板</td>        <td align="left">正点原子 i.MX6ULL Linux 阿尔法开发板</td>      </tr>    <tr>        <td align="center">uboot</td>        <td align="left">NXP官方提供的uboot，使用的uboot版本为U-Boot 2019.04</td>      </tr>    <tr>        <td align="center">linux内核</td>        <td align="left">linux-4.19.71(NXP官方提供)</td>      </tr></table>
              </div>
            </details>

<details class="folding-tag" blue><summary> 点击查看本文参考资料 </summary>
              <div class='content'>
              <table>    <tr>        <td align="center">分类</td>        <td align="center">网址</td>        <td align="center">说明</td>    </tr>    <tr>        <td align="center" rowspan="5">官方网站</td>        <td align="left"><a href="https://www.arm.com/" target="_blank">https://www.arm.com/</a></td>        <td align="left">ARM官方网站，在这里我们可以找到Cotex-Mx以及ARMVx的一些文档</td>    </tr>    <tr>        <td align="left"><a href="https://www.nxp.com.cn/" target="_blank">https://www.nxp.com.cn/ </a></td>        <td align="left">NXP官方网站</td>    </tr>    <tr>        <td align="left"><a href="https://www.nxpic.org.cn/" target="_blank">https://www.nxpic.org.cn/</a></td><td align="left">NXP 官方社区</td>    </tr>    <tr>        <td align="left"><a href="https://u-boot.readthedocs.io/en/latest/" target="_blank">https://u-boot.readthedocs.io/en/latest/</a></td><td align="left">u-boot官网</td>    </tr>    <tr>        <td align="left"><a href="https://www.kernel.org/" target="_blank">https://www.kernel.org/</a></td><td align="left">linux内核官网</td>    </tr></table>
              </div>
            </details>

<details class="folding-tag" blue><summary> 点击查看相关文件下载 </summary>
              <div class='content'>
              <table>    <tr>        <td align="center">分类</td>        <td align="center">网址</td>        <td align="center">说明</td>    </tr>    <tr>        <td align="center" rowspan="3">NXP</td>        <td align="left"><a href="https://github.com/nxp-imx" target="_blank">https://github.com/nxp-imx</a></td>        <td align="left">NXP imx开发资源GitHub组织，里边会有u-boot和linux内核的仓库</td>    </tr>    <tr>        <td align="left"><a href="https://github.com/nxp-imx/linux-imx/releases/tag/v4.19.71" target="_blank">nxp-imx/linux-imx/releases/tag/v4.19.71</a></td>        <td align="left">NXP linux内核仓库tags中的v4.19.71</td>    </tr>    <tr>        <td align="left"><a href="https://github.com/nxp-imx/uboot-imx/releases/tag/rel_imx_4.19.35_1.1.0" target="_blank">nxp-imx/uboot-imx/releases/tag/rel_imx_4.19.35_1.1.0</a></td>        <td align="left">NXP u-boot仓库tags中的rel_imx_4.19.35_1.1.0</td>    </tr>    <tr>        <td align="center" rowspan="2">I.MX6ULL</td>        <td align="left"><a href="https://www.nxp.com.cn/docs/en/data-sheet/IMX6ULLIEC.pdf" target="_blank">i.MX 6ULL Applications Processors for Industrial Products</a></td>        <td align="left">I.MX6ULL 芯片手册（datasheet，可以在线查看）</td>    </tr>    <tr>        <td align="left"><a href="https://www.nxp.com.cn/webapp/Download?colCode=IMX6ULLRM&lang_cd=zh" target="_blank">i.MX 6ULL Applications ProcessorReference Manual</a></td>        <td align="left">I.MX6ULL 参考手册（下载后才能查看，需要登录NXP官网）</td>    </tr>    <tr>        <td align="center" rowspan="2">Source Code</td>        <td align="left"><a href="https://elixir.bootlin.com/linux/latest/source" target="_blank">https://elixir.bootlin.com/linux/latest/source</a></td>        <td align="left">linux kernel源码</td>    </tr>    <tr>        <td align="left"><a href="https://elixir.bootlin.com/u-boot/latest/source" target="_blank">https://elixir.bootlin.com/u-boot/latest/source</a></td>        <td align="left">uboot源码</td>    </tr></table>
              </div>
            </details>

<h1 id="一、概述"><a href="#一、概述" class="headerlink" title="一、概述"></a><font size=3>一、概述</font></h1><p>其实大概翻一下linux内核的顶层 <a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/Makefile">Makefile</a> 就会发现，它和u-boot的顶层 <a target="_blank" rel="noopener" href="https://elixir.bootlin.com/u-boot/v2019.04/source/Makefile">Makefile</a> 结构是很类似的，大部分都差不多，之前已经详细去分析过u-boot的顶层Makefile了，可以看这里：<a href="https://sumumm.github.io/post/ca32061f.html">LV05-02-U-Boot-06-01-顶层Makefile基础解析 | 苏木</a>。这里一些基础的东西就不再详细分析了。</p>
<h1 id="二、make-xxx-defconfig"><a href="#二、make-xxx-defconfig" class="headerlink" title="二、make xxx_defconfig"></a><font size=3>二、make xxx_defconfig</font></h1><h2 id="1-打印信息"><a href="#1-打印信息" class="headerlink" title="1. 打印信息"></a><font size=3>1. 打印信息</font></h2><p>先看一下配置过程的打印信息吧：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">make V=0 ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- distclean</span><br><span class="line">make V=1 ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- imx_v6_v7_defconfig</span><br></pre></td></tr></table></figure>

<p>我们会在终端看到以下打印信息：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">make -f ./scripts/Makefile.build obj=scripts/basic</span><br><span class="line">  gcc -Wp,-MD,scripts/basic/.fixdep.d -Wall -Wmissing-prototypes -Wstrict-prototypes -O2 -fomit-frame-pointer -std=gnu89         -o scripts/basic/fixdep scripts/basic/fixdep.c   </span><br><span class="line">rm -f .tmp_quiet_recordmcount</span><br><span class="line">make -f ./scripts/Makefile.build obj=scripts/kconfig imx_v6_v7_defconfig</span><br><span class="line">  gcc -Wp,-MD,scripts/kconfig/.conf.o.d -Wall -Wmissing-prototypes -Wstrict-prototypes -O2 -fomit-frame-pointer -std=gnu89       -c -o scripts/kconfig/conf.o scripts/kconfig/conf.c</span><br><span class="line">  bison -oscripts/kconfig/zconf.tab.c -t -l scripts/kconfig/zconf.y</span><br><span class="line">  flex -oscripts/kconfig/zconf.lex.c -L scripts/kconfig/zconf.l</span><br><span class="line">  gcc -Wp,-MD,scripts/kconfig/.zconf.tab.o.d -Wall -Wmissing-prototypes -Wstrict-prototypes -O2 -fomit-frame-pointer -std=gnu89      -Iscripts/kconfig -c -o scripts/kconfig/zconf.tab.o scripts/kconfig/zconf.tab.c</span><br><span class="line">  gcc   -o scripts/kconfig/conf scripts/kconfig/conf.o scripts/kconfig/zconf.tab.o   </span><br><span class="line">scripts/kconfig/conf  --defconfig=arch/arm/configs/imx_v6_v7_defconfig Kconfig</span><br><span class="line"><span class="meta prompt_">#</span><span class="language-bash"></span></span><br><span class="line"><span class="language-bash"><span class="comment"># configuration written to .config</span></span></span><br><span class="line"><span class="meta prompt_">#</span></span><br></pre></td></tr></table></figure>

<p>后面我们分析的时候会用到。</p>
<h2 id="2-config目标"><a href="#2-config目标" class="headerlink" title="2. %config目标"></a><font size=3>2. %config目标</font></h2><p>第一次编译 Linux 之前都要使用“make xxx_defconfig”先配置 Linux 内核，在顶层 Makefile 中有“%config”这个目标。它定义在 <a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/Makefile#L533">Makefile - <em>%config</em></a>：</p>
<figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="section">%config: scripts_basic outputmakefile FORCE</span></span><br><span class="line">	<span class="variable">$(Q)</span><span class="variable">$(MAKE)</span> <span class="variable">$(build)</span>=scripts/kconfig <span class="variable">$@</span></span><br></pre></td></tr></table></figure>

<p>“%config”依赖 scripts_basic、outputmakefile 和 FORCE，“%config”真正有意义的依赖就只有 scripts_basic。其他的这几个变量这里直接加打印信息来看吧，就不逐个分析了：</p>
<figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="section">%config: scripts_basic outputmakefile FORCE</span></span><br><span class="line">	@echo <span class="string">&quot;Q=<span class="variable">$(Q)</span>&quot;</span></span><br><span class="line">	@echo <span class="string">&quot;MAKE=<span class="variable">$(MAKE)</span>&quot;</span></span><br><span class="line">	@echo <span class="string">&quot;build=<span class="variable">$(build)</span>&quot;</span></span><br><span class="line">	@echo <span class="string">&quot;@=<span class="variable">$@</span>&quot;</span></span><br><span class="line">	<span class="variable">$(Q)</span><span class="variable">$(MAKE)</span> <span class="variable">$(build)</span>=scripts/kconfig <span class="variable">$@</span></span><br></pre></td></tr></table></figure>

<p>然后执行：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">make V=0 ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- distclean</span><br><span class="line">make V=1 ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- imx_v6_v7_defconfig</span><br></pre></td></tr></table></figure>

<p>就会看到如下信息：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">Q=</span><br><span class="line">MAKE=make</span><br><span class="line">build=-f ./scripts/Makefile.build obj</span><br><span class="line">@=imx_v6_v7_defconfig</span><br></pre></td></tr></table></figure>

<p>所以上面的规则展开就是：</p>
<figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="section">%config: scripts_basic outputmakefile FORCE</span></span><br><span class="line">	make -f ./scripts/Makefile.build obj=scripts/kconfig imx_v6_v7_defconfig <span class="comment"># 也可以有@，视配置而定</span></span><br></pre></td></tr></table></figure>

<h2 id="3-build变量"><a href="#3-build变量" class="headerlink" title="3. build变量"></a><font size=3>3. build变量</font></h2><p>这个build变量定义在 <a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/scripts/Kbuild.include#L184">Kbuild.include - scripts&#x2F;Kbuild.include - <em>build</em></a>：</p>
<figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">###</span></span><br><span class="line"><span class="comment"># Shorthand for $(Q)$(MAKE) -f scripts/Makefile.build obj=</span></span><br><span class="line"><span class="comment"># Usage:</span></span><br><span class="line"><span class="comment"># $(Q)$(MAKE) $(build)=dir</span></span><br><span class="line">build := -f <span class="variable">$(srctree)</span>/scripts/Makefile.build obj</span><br></pre></td></tr></table></figure>

<p>这个srctree是定义在顶层 <a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/Makefile#L190">Makefile - <em>srctree</em></a> 中，分析之后srctree&#x3D;<code>.</code>。所以这里就是：</p>
<figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">build := -f ./scripts/Makefile.build obj</span><br></pre></td></tr></table></figure>

<h2 id="4-scripts-basic"><a href="#4-scripts-basic" class="headerlink" title="4. scripts_basic"></a><font size=3>4. scripts_basic</font></h2><p>接下来看一下这个scripts_basic规则，它定义在 <a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/Makefile#L465">Makefile - <em>scripts_basic</em></a> ：</p>
<figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Basic helpers built in scripts/basic/</span></span><br><span class="line">PHONY += scripts_basic</span><br><span class="line"><span class="section">scripts_basic:</span></span><br><span class="line">	<span class="variable">$(Q)</span><span class="variable">$(MAKE)</span> <span class="variable">$(build)</span>=scripts/basic</span><br><span class="line">	<span class="variable">$(Q)</span>rm -f .tmp_quiet_recordmcount</span><br></pre></td></tr></table></figure>

<p>前面我们已经打印了相关的变量的值，所以这里其实就是：</p>
<figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="section">scripts_basic:</span></span><br><span class="line">    @make -f ./scripts/Makefile.build obj=scripts/basic <span class="comment"># 也可以没有@，视配置而定</span></span><br><span class="line">    @rm -f . tmp_quiet_recordmcount                     <span class="comment"># 也可以没有@</span></span><br></pre></td></tr></table></figure>

<h2 id="5-Makefile-build"><a href="#5-Makefile-build" class="headerlink" title="5. Makefile.build"></a><font size=3>5. Makefile.build</font></h2><p>从前面的%config和scripts_basic目标可以知道，“make xxx_defconfig“配置 Linux 的时候如下两行命令会执行脚本 <a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/scripts/Makefile.build">Makefile.build - scripts&#x2F;Makefile.build</a> ：</p>
<figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">@make -f ./scripts/Makefile.build obj=scripts/basic</span><br><span class="line">@make -f ./scripts/Makefile.build obj=scripts/kconfig xxx_defconfig</span><br></pre></td></tr></table></figure>

<h3 id="5-1-scripts-basic-目标对应的命令"><a href="#5-1-scripts-basic-目标对应的命令" class="headerlink" title="5.1 scripts_basic 目标对应的命令"></a><font size=3>5.1 scripts_basic 目标对应的命令</font></h3><p>scripts_basic 目标对应的命令为：</p>
<figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">@make -f ./scripts/Makefile.build obj=scripts/basic</span><br></pre></td></tr></table></figure>

<p>我们打开 <a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/scripts/Makefile.build#L43">Makefile.build - scripts&#x2F;Makefile.build</a> 文件，会看到这两个变量：</p>
<figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># The filename Kbuild has precedence over Makefile</span></span><br><span class="line">kbuild-dir := <span class="variable">$(<span class="built_in">if</span> $(<span class="built_in">filter</span> /%,<span class="variable">$(src)</span>)</span>,<span class="variable">$(src)</span>,<span class="variable">$(srctree)</span>/<span class="variable">$(src)</span>)</span><br><span class="line">kbuild-file := <span class="variable">$(<span class="built_in">if</span> $(<span class="built_in">wildcard</span> $(kbuild-<span class="built_in">dir</span>)</span>/Kbuild),$(kbuild-dir)/Kbuild,$(kbuild-dir)/Makefile)</span><br><span class="line"><span class="keyword">include</span> $(kbuild-file)</span><br></pre></td></tr></table></figure>

<p>这里的src变量定义在 <a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/scripts/Makefile.build#L6">Makefile.build - scripts&#x2F;Makefile.build - <em>src</em></a></p>
<figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">src := <span class="variable">$(obj)</span></span><br></pre></td></tr></table></figure>

<p>所以 src&#x3D;scripts&#x2F;basic，此时我们将 kbuild-dir 和 kbuild-file 展开：</p>
<figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">kbuild-dir=./scripts/basic</span><br><span class="line">kbuild-file=./scripts/basic/Makefile</span><br><span class="line"><span class="keyword">include</span> ./scripts/basic/Makefile</span><br></pre></td></tr></table></figure>

<p>继续往后分析，就可以看到这个目标<a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/scripts/Makefile.build#L80">Makefile.build - scripts&#x2F;Makefile.build - <em>__build</em></a>：</p>
<figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># We keep a list of all modules in $(MODVERDIR)</span></span><br><span class="line"></span><br><span class="line"><span class="section">__build: $(if <span class="variable">$(KBUILD_BUILTIN)</span>,$(builtin-target) $(lib-target) $(extra-y)) \</span></span><br><span class="line">	 <span class="variable">$(<span class="built_in">if</span> <span class="variable">$(KBUILD_MODULES)</span>,$(obj-m)</span> $(modorder-target)) \</span><br><span class="line">	 $(subdir-ym) <span class="variable">$(always)</span></span><br><span class="line">	@:</span><br></pre></td></tr></table></figure>

<p>__build 是默认目标，因为命令“@make -f .&#x2F;scripts&#x2F;Makefile.build obj&#x3D;scripts&#x2F;basic”没有指定目标，所以会使用到默认目标__build。在顶层 Makefile 中，KBUILD_BUILTIN 为 1， KBUILD_MODULES 为空，因此展开后目标__build 为：</p>
<figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="section">__build:$(builtin-target) $(lib-target) $(extra-y)) $(subdir-ym) <span class="variable">$(always)</span></span></span><br><span class="line">	@:</span><br></pre></td></tr></table></figure>

<p>可以看出目标__build 有 5 个依赖：builtin-target、lib-target、extra-y、subdir-ym 和 always。我们直接添加打印信息看一下：</p>
<figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="section">__build: $(if <span class="variable">$(KBUILD_BUILTIN)</span>,$(builtin-target) $(lib-target) $(extra-y)) \</span></span><br><span class="line">	 <span class="variable">$(<span class="built_in">if</span> <span class="variable">$(KBUILD_MODULES)</span>,$(obj-m)</span> $(modorder-target)) \</span><br><span class="line">	 $(subdir-ym) <span class="variable">$(always)</span></span><br><span class="line">	@:</span><br><span class="line">	@echo <span class="string">&quot;builtin-target=&quot;</span>$(builtin-target) </span><br><span class="line">	@echo <span class="string">&quot;lib-target=&quot;</span>$(lib-target) </span><br><span class="line">	@echo <span class="string">&quot;extra-y=&quot;</span>$(extra-y)</span><br><span class="line">	@echo <span class="string">&quot;subdir-ym=&quot;</span>$(subdir-ym) </span><br><span class="line">	@echo <span class="string">&quot;always=&quot;</span><span class="variable">$(always)</span></span><br></pre></td></tr></table></figure>

<p>然后执行：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">make V=0 ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- distclean</span><br><span class="line">make V=1 ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- imx_v6_v7_defconfig</span><br></pre></td></tr></table></figure>

<p>会看到这 5 个依赖的具体内容如下：</p>
<figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">builtin-target=</span><br><span class="line">lib-target=</span><br><span class="line">extra-y=</span><br><span class="line">subdir-ym=</span><br><span class="line">always=scripts/basic/fixdep</span><br></pre></td></tr></table></figure>

<p>所以最终的__build为：</p>
<figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="section">__build: scripts/basic/fixdep</span></span><br><span class="line">	@:</span><br></pre></td></tr></table></figure>

<p>__build 依赖于 scripts&#x2F;basic&#x2F;fixdep，所以要先将 scripts&#x2F;basic&#x2F;fixdep文件编译成 fixdep。 </p>
<p>综上所述，scripts_basic 目标的作用就是编译出 scripts&#x2F;basic&#x2F;fixdep软件。</p>
<h3 id="5-2-config-目标对应的命令"><a href="#5-2-config-目标对应的命令" class="headerlink" title="5.2 %config 目标对应的命令"></a><font size=3>5.2 %config 目标对应的命令</font></h3><p>%config 目标对应的命令为：</p>
<figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">make -f ./scripts/Makefile.build obj=scripts/kconfig xxx_defconfig</span><br></pre></td></tr></table></figure>

<p>我们推测一下，<a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/scripts/Makefile.build#L80">Makefile.build - scripts&#x2F;Makefile.build</a>里面应该有一个defconfig相关的目标才对，但是去搜一下好像没有，我们和前面一样，先看一下<a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/scripts/Makefile.build#L43">Makefile.build - scripts&#x2F;Makefile.build</a> 中的kbuild-dir和kbuild-file：</p>
<figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">kbuild-dir := <span class="variable">$(<span class="built_in">if</span> $(<span class="built_in">filter</span> /%,<span class="variable">$(src)</span>)</span>,<span class="variable">$(src)</span>,<span class="variable">$(srctree)</span>/<span class="variable">$(src)</span>)</span><br><span class="line">kbuild-file := <span class="variable">$(<span class="built_in">if</span> $(<span class="built_in">wildcard</span> $(kbuild-<span class="built_in">dir</span>)</span>/Kbuild),$(kbuild-dir)/Kbuild,$(kbuild-dir)/Makefile)</span><br><span class="line"><span class="keyword">include</span> $(kbuild-file)</span><br></pre></td></tr></table></figure>

<p>我们知道srctree&#x3D;<code>.</code>，src&#x3D;scripts&#x2F;kconfig，所以这里展开就是：</p>
<figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">kbuild-dir = ./scripts/kconfig</span><br><span class="line">kbuild-file = ./scripts/kconfig/Makefile</span><br><span class="line"><span class="keyword">include</span> ./scripts/kconfig/Makefile</span><br></pre></td></tr></table></figure>

<p>可以看出，Makefile.build 会读取 scripts&#x2F;kconfig&#x2F;Makefile 中的内容，此文件有如下所示内容<a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/scripts/kconfig/Makefile#L103">Makefile - scripts&#x2F;kconfig&#x2F;Makefile - <em>%_defconfig</em></a>：</p>
<figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="section">%_defconfig: <span class="variable">$(obj)</span>/conf</span></span><br><span class="line">	<span class="variable">$(Q)</span><span class="variable">$&lt;</span> <span class="variable">$(silent)</span> --defconfig=arch/<span class="variable">$(SRCARCH)</span>/configs/<span class="variable">$@</span> <span class="variable">$(Kconfig)</span></span><br></pre></td></tr></table></figure>

<p>目标%_defconfig 与 xxx_defconfig 匹配，所以会执行这条规则，SRCARCH定义在<a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/Makefile#L326">Makefile - <em>SRCARCH</em></a>，我们编译的是ARM平台，这里就有ARCARCH&#x3D;arm。Kconfig定义在<a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/scripts/kconfig/Makefile#L9">Makefile - scripts&#x2F;kconfig&#x2F;Makefile - <em>Kconfig</em></a>，最后它的值为Kconfig，这里将其展开就是：</p>
<figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="section">%_defconfig: scripts/kconfig/conf</span></span><br><span class="line">    @ scripts/kconfig/conf --defconfig=arch/arm/configs/%_defconfig Kconfig</span><br></pre></td></tr></table></figure>

<p>%_defconfig依赖scripts&#x2F;kconfig&#x2F;conf，所以会编译scripts&#x2F;kconfig&#x2F;conf.c生成conf这个软件。 此软件就会将 %_defconfig 中的配置输出到.config 文件中，最终生成 Linux kernel 根目录下的.config 文件。具体怎么生成的这里就没有仔细去研究了，大概知道这里是这样生成的就可以了。</p>
<h1 id="三、make-all"><a href="#三、make-all" class="headerlink" title="三、make all"></a><font size=3>三、make all</font></h1><p>使用命令“make xxx_defconfig”配置好 Linux 内核以后就可以使用“make”或者“make all” 命令进行编译。</p>
<h2 id="1-all目标"><a href="#1-all目标" class="headerlink" title="1. _all目标"></a><font size=3>1. _all目标</font></h2><p>我们先来看一下顶层Makefile中关于_all目标的一些相关的内容，它在 <a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/Makefile#L15">Makefile - <em>_all</em></a> 和<a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/Makefile#L541">Makefile - <em>_all</em></a>：</p>
<figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># That&#x27;s our default target when none is given on the command line</span></span><br><span class="line">PHONY := _all</span><br><span class="line"><span class="section">_all:</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># ......</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># If building an external module we do not care about the all: rule</span></span><br><span class="line"><span class="comment"># but instead _all depend on modules</span></span><br><span class="line">PHONY += all</span><br><span class="line"><span class="keyword">ifeq</span> (<span class="variable">$(KBUILD_EXTMOD)</span>,)</span><br><span class="line"><span class="section">_all: all     # (1)</span></span><br><span class="line"><span class="keyword">else</span></span><br><span class="line"><span class="section">_all: modules # (2)</span></span><br><span class="line"><span class="keyword">endif</span></span><br></pre></td></tr></table></figure>

<p>_all 是默认目标，如果使用命令“make”编译 Linux 的话此目标就会被匹配。继续往下的话，我们看到还有一个变量来控制默认目标的依赖，如果 KBUILD_EXTMOD 为空的话 ifeq中的(1)代码成立。添加打印信息就会发现这里我们执行make all的话，(1)是成立的，所以_all目标又依赖于all。</p>
<h2 id="2-all目标"><a href="#2-all目标" class="headerlink" title="2. all目标"></a><font size=3>2. all目标</font></h2><p>我们再看一下all目标，它定义在 <a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/Makefile#L597">Makefile - <em>all</em></a> ：</p>
<figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># The all: target is the default when no target is given on the</span></span><br><span class="line"><span class="comment"># command line.</span></span><br><span class="line"><span class="comment"># This allow a user to issue only &#x27;make&#x27; to build a kernel including modules</span></span><br><span class="line"><span class="comment"># Defaults to vmlinux, but the arch makefile usually adds further targets</span></span><br><span class="line"><span class="section">all: vmlinux</span></span><br></pre></td></tr></table></figure>

<p>目标 all 依赖 vmlinux，所以接下来的重点就是 vmlinux！</p>
<h2 id="3-vmlinux目标"><a href="#3-vmlinux目标" class="headerlink" title="3. vmlinux目标"></a><font size=3>3. vmlinux目标</font></h2><h3 id="3-1-vmlinux简单展开"><a href="#3-1-vmlinux简单展开" class="headerlink" title="3.1 vmlinux简单展开"></a><font size=3>3.1 vmlinux简单展开</font></h3><p>vmlinux目标定义在 <a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/Makefile#L1019">Makefile - <em>vmlinux</em></a>：</p>
<figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="section">vmlinux: scripts/link-vmlinux.sh autoksyms_recursive $(vmlinux-deps) FORCE</span></span><br><span class="line"><span class="keyword">ifdef</span> CONFIG_HEADERS_CHECK</span><br><span class="line">	<span class="variable">$(Q)</span><span class="variable">$(MAKE)</span> -f <span class="variable">$(srctree)</span>/Makefile headers_check</span><br><span class="line"><span class="keyword">endif</span></span><br><span class="line"><span class="keyword">ifdef</span> CONFIG_GDB_SCRIPTS</span><br><span class="line">	<span class="variable">$(Q)</span>ln -fsn <span class="variable">$(<span class="built_in">abspath</span> <span class="variable">$(srctree)</span>/scripts/gdb/vmlinux-gdb.py)</span></span><br><span class="line"><span class="keyword">endif</span></span><br><span class="line">	+<span class="variable">$(<span class="built_in">call</span> if_changed,link-vmlinux)</span></span><br></pre></td></tr></table></figure>

<p>可以看出目标 vmlinux 依赖 scripts&#x2F;link-vmlinux.sh、vmlinux-deps和FORCE，其中vmlinux-deps定义在 <a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/Makefile#L989">Makefile - <em>vmlinux-deps</em></a> ：</p>
<figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">vmlinux-deps := <span class="variable">$(KBUILD_LDS)</span> <span class="variable">$(KBUILD_VMLINUX_INIT)</span> <span class="variable">$(KBUILD_VMLINUX_MAIN)</span> <span class="variable">$(KBUILD_VMLINUX_LIBS)</span></span><br></pre></td></tr></table></figure>

<p>这几个变量都定义在这个位置 <a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/Makefile#L980">Makefile - <em>Externally visible symbols</em></a>：</p>
<figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Externally visible symbols (used by link-vmlinux.sh)</span></span><br><span class="line"><span class="keyword">export</span> KBUILD_VMLINUX_INIT := $(head-y) $(init-y)</span><br><span class="line"><span class="keyword">export</span> KBUILD_VMLINUX_MAIN := $(core-y) $(libs-y2) $(drivers-y) $(net-y) $(virt-y)</span><br><span class="line"><span class="keyword">export</span> KBUILD_VMLINUX_LIBS := $(libs-y1)</span><br><span class="line"><span class="keyword">export</span> KBUILD_LDS          := arch/<span class="variable">$(SRCARCH)</span>/kernel/vmlinux.lds</span><br></pre></td></tr></table></figure>

<p>前面我们知道 SRCARCH&#x3D;arm，所以KBUILD_LDS:&#x3D; arch&#x2F;arm&#x2F;kernel&#x2F;vmlinux.lds，所以vmlinux的依赖为：</p>
<figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">scripts/link-vmlinux.sh autoksyms_recursive $(head-y) $(init-y) $(core-y) $(libs-y2) $(drivers-y) $(net-y) $(virt-y) $(libs-y1) arch/<span class="variable">$(SRCARCH)</span>/kernel/vmlinux.lds FORCE</span><br></pre></td></tr></table></figure>

<p>我们搜索一下 CONFIG_HEADERS_CHECK 和 CONFIG_GDB_SCRIPTS，会发现NXP官方的evk评估板所对应的默认配置文件 imx_v6_v7_defconfig 是没有这两个定义的，最终的.config中也没有配置这两个选项。这里就先不管了，然后我们展开一下这个vmlinux：</p>
<figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="section">vmlinux: scripts/link-vmlinux.sh autoksyms_recursive $(head-y) $(init-y) $(core-y) $(libs-y2) $(drivers-y) $(net-y) $(virt-y) $(libs-y1) arch/<span class="variable">$(SRCARCH)</span>/kernel/vmlinux.lds FORCE</span></span><br><span class="line">	+<span class="variable">$(<span class="built_in">call</span> if_changed,link-vmlinux)</span></span><br></pre></td></tr></table></figure>

<p>当依赖准备好后，调用if_changed这个函数就是生成vmlinux。</p>
<h3 id="3-2-依赖的变量"><a href="#3-2-依赖的变量" class="headerlink" title="3.2 依赖的变量"></a><font size=3>3.2 依赖的变量</font></h3><h4 id="3-2-1-head-y"><a href="#3-2-1-head-y" class="headerlink" title="3.2.1 head-y"></a><font size=3>3.2.1 head-y</font></h4><p>head-y这个变量是定义在 <a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/arch/arm/Makefile#L138">Makefile - arch&#x2F;arm&#x2F;Makefile - <em>head-y</em></a>：</p>
<figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#Default value</span></span><br><span class="line">head-y		:= arch/arm/kernel/head<span class="variable">$(MMUEXT)</span>.o</span><br></pre></td></tr></table></figure>

<p>当不使能 MMU 的话 MMUEXT&#x3D;-nommu，如果使能 MMU 的话为空，因此 head-y 最终的 值为：</p>
<figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">head-y = arch/arm/kernel/head.o</span><br></pre></td></tr></table></figure>

<h4 id="3-2-2-init-y、drivers-y-和-net-y"><a href="#3-2-2-init-y、drivers-y-和-net-y" class="headerlink" title="3.2.2 init-y、drivers-y 和 net-y"></a><font size=3>3.2.2 init-y、drivers-y 和 net-y</font></h4><p>init-y、drivers-y 和 net-y这三个变量是定义在 <a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/Makefile#L580">Makefile - <em>Objects we will link into vmlinux &#x2F; subdirs we need to visit</em></a>：</p>
<figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">init-y		:= init/</span><br><span class="line">drivers-y	:= drivers/ sound/ firmware/</span><br><span class="line">net-y		:= net/</span><br></pre></td></tr></table></figure>

<p>还有一个位置也有，在这里<a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/Makefile#L972">Makefile</a>：</p>
<figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">init-y		:= <span class="variable">$(<span class="built_in">patsubst</span> %/, %/built-in.a, $(init-y)</span>)</span><br><span class="line">core-y		:= <span class="variable">$(<span class="built_in">patsubst</span> %/, %/built-in.a, $(core-y)</span>)</span><br><span class="line">drivers-y	:= <span class="variable">$(<span class="built_in">patsubst</span> %/, %/built-in.a, $(drivers-y)</span>)</span><br><span class="line">net-y		:= <span class="variable">$(<span class="built_in">patsubst</span> %/, %/built-in.a, $(net-y)</span>)</span><br></pre></td></tr></table></figure>

<p>所以init-y、drivers-y 和 net-y 最终的值为：</p>
<figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">nit-y = init/built-in.a</span><br><span class="line">drivers-y = drivers/built-in.a sound/built-in.a firmware/built-in.a</span><br><span class="line">net-y = net/built-in.a</span><br></pre></td></tr></table></figure>

<h4 id="3-2-3-libs-y1和libs-y2"><a href="#3-2-3-libs-y1和libs-y2" class="headerlink" title="3.2.3 libs-y1和libs-y2"></a><font size=3>3.2.3 libs-y1和libs-y2</font></h4><p>libs-y1、 libs-y2基本和 init-y 一样，在顶层 <a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/Makefile#L976">Makefile - <em>libs-y1和libs-y2</em></a> 中有如下定义：</p>
<figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">libs-y1		:= <span class="variable">$(<span class="built_in">patsubst</span> %/, %/lib.a, $(libs-y)</span>)</span><br><span class="line">libs-y2		:= <span class="variable">$(<span class="built_in">patsubst</span> %/, %/built-in.a, $(<span class="built_in">filter</span>-out %.a, $(libs-y)</span>))</span><br></pre></td></tr></table></figure>

<p>其中libs-y定义在<a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/Makefile#L584">Makefile - <em>libs-y</em></a>：</p>
<figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">libs-y		:= lib/</span><br></pre></td></tr></table></figure>

<p>另外，这个libs-y在<a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/arch/arm/Makefile#L300">Makefile - arch&#x2F;arm&#x2F;Makefile - <em>libs-y</em></a> 中也有定义：</p>
<figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">libs-y				:= arch/arm/lib/ $(libs-y)</span><br></pre></td></tr></table></figure>

<p>最终libs-y的值为：</p>
<figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">libs-y = arch/arm/lib lib/</span><br></pre></td></tr></table></figure>

<p>libs-y2中filter-out是反过滤函数，就是匹配除.a结尾的文件以外的文件，然后再匹配目录中的built-in.a，所以这里就有</p>
<figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">libs-y1		:= arch/arm/lib/lib.a lib/lib.a</span><br><span class="line">libs-y2		:= arch/arm/lib/built-in.a lib/built-in.a</span><br></pre></td></tr></table></figure>

<h4 id="3-2-4-core-y"><a href="#3-2-4-core-y" class="headerlink" title="3.2.4 core-y"></a><font size=3>3.2.4 core-y</font></h4><p>core-y定义在 <a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/Makefile#L585">Makefile - <em>Objects we will link into vmlinux &#x2F; subdirs we need to visit</em></a>：</p>
<figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">core-y		:= usr/</span><br></pre></td></tr></table></figure>

<p>在 <a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/Makefile#L963">Makefile - <em>core-y</em></a> 这里会追加一些值：</p>
<figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">core-y		+= kernel/ certs/ mm/ fs/ ipc/ security/ crypto/ block/</span><br><span class="line"><span class="comment">#......</span></span><br><span class="line">core-y		:= <span class="variable">$(<span class="built_in">patsubst</span> %/, %/built-in.a, $(core-y)</span>)</span><br></pre></td></tr></table></figure>

<p>在 <a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/arch/arm/Makefile#L291">Makefile - arch&#x2F;arm&#x2F;Makefile - <em>core-y</em></a> 也会追加一些值：</p>
<figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">core-<span class="variable">$(CONFIG_FPE_NWFPE)</span>	+= arch/arm/nwfpe/</span><br><span class="line">core-<span class="variable">$(CONFIG_FPE_FASTFPE)</span>	+= <span class="variable">$(FASTFPE_OBJ)</span></span><br><span class="line">core-<span class="variable">$(CONFIG_VFP)</span>		+= arch/arm/vfp/</span><br><span class="line">core-<span class="variable">$(CONFIG_XEN)</span>		+= arch/arm/xen/</span><br><span class="line">core-<span class="variable">$(CONFIG_KVM_ARM_HOST)</span> 	+= arch/arm/kvm/</span><br><span class="line">core-<span class="variable">$(CONFIG_VDSO)</span>		+= arch/arm/vdso/</span><br><span class="line"></span><br><span class="line"><span class="comment"># If we have a machine-specific directory, then include it in the build.</span></span><br><span class="line">core-y				+= arch/arm/kernel/ arch/arm/mm/ arch/arm/common/</span><br><span class="line">core-y				+= arch/arm/probes/</span><br><span class="line">core-y				+= arch/arm/net/</span><br><span class="line">core-y				+= arch/arm/crypto/</span><br><span class="line">core-y				+= arch/arm/firmware/</span><br><span class="line">core-y				+= <span class="variable">$(machdirs)</span> <span class="variable">$(platdirs)</span></span><br><span class="line"></span><br></pre></td></tr></table></figure>

<p>这里有一部分根据不同的配置向 core-y 追加不同的值，比如使能 VFP 的话就会在.config 中有 CONFIG_VFP&#x3D;y 这一行，那么 core-y 就会追加“arch&#x2F;arm&#x2F;vfp&#x2F;”。另外一部分就是对 core-y 直接追加的值。所以总的来说：</p>
<figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">core-y		        := usr/</span><br><span class="line">core-y		        += kernel/ certs/ mm/ fs/ ipc/ security/ crypto/ block/</span><br><span class="line">core-y				+= arch/arm/kernel/ arch/arm/mm/ arch/arm/common/</span><br><span class="line">core-y				+= arch/arm/probes/</span><br><span class="line">core-y				+= arch/arm/net/</span><br><span class="line">core-y				+= arch/arm/crypto/</span><br><span class="line">core-y				+= arch/arm/firmware/</span><br><span class="line">core-y				+= <span class="variable">$(machdirs)</span> <span class="variable">$(platdirs)</span></span><br><span class="line">core-<span class="variable">$(CONFIG_FPE_NWFPE)</span>	+= arch/arm/nwfpe/</span><br><span class="line">core-<span class="variable">$(CONFIG_FPE_FASTFPE)</span>	+= <span class="variable">$(FASTFPE_OBJ)</span></span><br><span class="line">core-<span class="variable">$(CONFIG_VFP)</span>		    += arch/arm/vfp/</span><br><span class="line">core-<span class="variable">$(CONFIG_XEN)</span>		    += arch/arm/xen/</span><br><span class="line">core-<span class="variable">$(CONFIG_KVM_ARM_HOST)</span> += arch/arm/kvm/</span><br><span class="line">core-<span class="variable">$(CONFIG_VDSO)</span>		    += arch/arm/vdso/</span><br></pre></td></tr></table></figure>

<p>最后有一句<a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/Makefile#L973">Makefile - <em>core-y</em></a>：</p>
<figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">core-y		:= <span class="variable">$(<span class="built_in">patsubst</span> %/, %/built-in.a, $(core-y)</span>)</span><br></pre></td></tr></table></figure>

<p>这里是core-y最终匹配的文件，就是匹配上面所有的目录中的built-in.a文件。</p>
<h4 id="3-2-5-总结"><a href="#3-2-5-总结" class="headerlink" title="3.2.5 总结"></a><font size=3>3.2.5 总结</font></h4><p>这些变量都是一些 built-in.o 或.a 等文件，这个和 uboot 一样，都是将相应目录中的源码文件进行编译，然后在各自目录下生成 built-in.o 文件，有些生成了.a 库文件。最终将这些 built-in.o 和.a 文 件进行链接即可形成 ELF 格式的可执行文件，也就是 vmlinux！但是链接是需要链接脚本的， vmlinux 的依赖 arch&#x2F;arm&#x2F;kernel&#x2F;vmlinux.lds 就是整个 Linux 的链接脚本。</p>
<h3 id="3-3-if-changed函数"><a href="#3-3-if-changed函数" class="headerlink" title="3.3 if_changed函数"></a><font size=3>3.3 if_changed函数</font></h3><p>接下来我们来看一下if_changed函数，前面我们将vmlinux目标的规则展开得到：</p>
<figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="section">vmlinux: scripts/link-vmlinux.sh autoksyms_recursive $(head-y) $(init-y) $(core-y) $(libs-y2) $(drivers-y) $(net-y) $(virt-y) $(libs-y1) arch/<span class="variable">$(SRCARCH)</span>/kernel/vmlinux.lds FORCE</span></span><br><span class="line">	+<span class="variable">$(<span class="built_in">call</span> if_changed,link-vmlinux)</span></span><br></pre></td></tr></table></figure>

<p>这里<code>+</code>表示该命令结果不可忽略。这里表示将if_changed函数的结果作为最终生成 vmlinux 的命令。，link-vmlinux 是函数 if_changed 的 参数，函数 if_changed 定义在文件 <a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/scripts/Kbuild.include#L259">Kbuild.include - scripts&#x2F;Kbuild.include - <em>if_changed</em></a> 中：</p>
<figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Execute command if command has changed or prerequisite(s) are updated.</span></span><br><span class="line">if_changed = <span class="variable">$(<span class="built_in">if</span> $(<span class="built_in">strip</span> $(any-prereq)</span> $(arg-check)),                       \</span><br><span class="line">	@set -e;                                                             \</span><br><span class="line">	$(echo-cmd) $(cmd_$(1));                                             \</span><br><span class="line">	printf &#x27;%s\n&#x27; &#x27;cmd_<span class="variable">$@</span> := $(make-cmd)&#x27; &gt; $(dot-target).cmd, @:)</span><br></pre></td></tr></table></figure>

<ul>
<li><p>any-prereq 用于检查依赖文件是否有变化，如果依赖文件有变化那么 any-prereq 就不为 空，否则就为空。</p>
</li>
<li><p>arg-check 用于检查参数是否有变化，如果没有变化那么 arg-check 就为空。</p>
</li>
<li><p><code>@set -e</code>告诉 bash，如果任何语句的执行结果不为 true(也就是执行出错)的 话就直接退出。</p>
</li>
<li><p><code>$(echo-cmd)</code>用于打印命令执行过程，比如在链接 vmlinux 的时候就会输出 “LINK vmlinux”。</p>
</li>
<li><p><code>$(cmd_$(1))</code>中的<code>$(1)</code>表示参数，也就是 link-vmlinux，因此<code>$(cmd_$(1))</code>表示 执行 cmd_link-vmlinux 的内容。</p>
</li>
</ul>
<h4 id="3-3-1-any-prereq"><a href="#3-3-1-any-prereq" class="headerlink" title="3.3.1 any-prereq"></a><font size=3>3.3.1 any-prereq</font></h4><p>any-prereq定义在 <a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/scripts/Kbuild.include#L259">Kbuild.include - scripts&#x2F;Kbuild.include - <em>any-prereq</em></a>：</p>
<figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Find any prerequisites that is newer than target or that does not exist.</span></span><br><span class="line"><span class="comment"># PHONY targets skipped in both cases.</span></span><br><span class="line">any-prereq = <span class="variable">$(<span class="built_in">filter</span>-out <span class="variable">$(PHONY)</span>,<span class="variable">$?</span>)</span> <span class="variable">$(<span class="built_in">filter</span>-out <span class="variable">$(PHONY)</span> $(<span class="built_in">wildcard</span> <span class="variable">$^</span>)</span>,<span class="variable">$^</span>)</span><br></pre></td></tr></table></figure>

<h4 id="3-3-2-arg-check"><a href="#3-3-2-arg-check" class="headerlink" title="3.3.2 arg-check"></a><font size=3>3.3.2 arg-check</font></h4><p>arg-check定义在 <a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/scripts/Kbuild.include#L238">Kbuild.include - scripts&#x2F;Kbuild.include - <em>arg-check</em></a>：</p>
<figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">ifneq</span> (<span class="variable">$(KBUILD_NOCMDDEP)</span>,1)</span><br><span class="line"><span class="comment"># Check if both arguments are the same including their order. Result is empty</span></span><br><span class="line"><span class="comment"># string if equal. User may override this check using make KBUILD_NOCMDDEP=1</span></span><br><span class="line">arg-check = <span class="variable">$(<span class="built_in">filter</span>-out $(<span class="built_in">subst</span> <span class="variable">$(space)</span>,<span class="variable">$(space_escape)</span>,$(<span class="built_in">strip</span> $(cmd_<span class="variable">$@</span>)</span>)), \</span><br><span class="line">                         <span class="variable">$(<span class="built_in">subst</span> <span class="variable">$(space)</span>,<span class="variable">$(space_escape)</span>,$(<span class="built_in">strip</span> $(cmd_$1)</span>)))</span><br><span class="line"><span class="keyword">else</span></span><br><span class="line">arg-check = <span class="variable">$(<span class="built_in">if</span> $(<span class="built_in">strip</span> $(cmd_<span class="variable">$@</span>)</span>),,1)</span><br><span class="line"><span class="keyword">endif</span></span><br></pre></td></tr></table></figure>

<h4 id="3-3-3-cmd-1"><a href="#3-3-3-cmd-1" class="headerlink" title="3.3.3 cmd_$(1)"></a><font size=3>3.3.3 cmd_$(1)</font></h4><p>接下来看一下这个<code>cmd_$(1)</code>，前面我们知道这个是 cmd_link-vmlinux，它定义在 <a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/Makefile#L1015">Makefile - <em>cmd_link-vmlinux</em></a>：</p>
<figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Final link of vmlinux with optional arch pass after final link</span></span><br><span class="line">cmd_link-vmlinux =                                                 \</span><br><span class="line">	<span class="variable">$(CONFIG_SHELL)</span> <span class="variable">$&lt;</span> <span class="variable">$(LD)</span> <span class="variable">$(KBUILD_LDFLAGS)</span> <span class="variable">$(LDFLAGS_vmlinux)</span> ;    \</span><br><span class="line">	<span class="variable">$(<span class="built_in">if</span> <span class="variable">$(ARCH_POSTLINK)</span>, <span class="variable">$(MAKE)</span> -f <span class="variable">$(ARCH_POSTLINK)</span> <span class="variable">$@</span>, true)</span></span><br></pre></td></tr></table></figure>

<ul>
<li>CONFIG_SHELL定义在<a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/Makefile#L353">Makefile - <em>CONFIG_SHELL</em></a></li>
</ul>
<figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># SHELL used by kbuild</span></span><br><span class="line">CONFIG_SHELL := <span class="variable">$(<span class="built_in">shell</span> <span class="built_in">if</span> [ -x &quot;$$BASH&quot; ]; then echo $$BASH; \</span></span><br><span class="line"><span class="variable">	  else <span class="built_in">if</span> [ -x /bin/bash ]; then echo /bin/bash; \</span></span><br><span class="line"><span class="variable">	  else echo sh; fi ; fi)</span></span><br></pre></td></tr></table></figure>

<p>最终CONFIG_SHELL&#x3D;&#x2F;bin&#x2F;bash。</p>
<ul>
<li><code>$&lt;</code> 表示目标 vmlinux 的第一个依赖文件：</li>
</ul>
<figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="section">vmlinux: scripts/link-vmlinux.sh autoksyms_recursive $(vmlinux-deps) FORCE</span></span><br><span class="line"><span class="keyword">ifdef</span> CONFIG_HEADERS_CHECK</span><br><span class="line">	<span class="variable">$(Q)</span><span class="variable">$(MAKE)</span> -f <span class="variable">$(srctree)</span>/Makefile headers_check</span><br><span class="line"><span class="keyword">endif</span></span><br><span class="line"><span class="keyword">ifdef</span> CONFIG_GDB_SCRIPTS</span><br><span class="line">	<span class="variable">$(Q)</span>ln -fsn <span class="variable">$(<span class="built_in">abspath</span> <span class="variable">$(srctree)</span>/scripts/gdb/vmlinux-gdb.py)</span></span><br><span class="line"><span class="keyword">endif</span></span><br><span class="line">	+<span class="variable">$(<span class="built_in">call</span> if_changed,link-vmlinux)</span></span><br></pre></td></tr></table></figure>

<p>在这里<code>$&lt;</code>就是scripts&#x2F;link-vmlinux.sh。</p>
<ul>
<li>LD就是链接工具，就定义在<a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/Makefile#L372">Makefile - <em>LD</em></a>，这里就是LD&#x3D; arm-linux-gnueabihf-ld。</li>
<li>KBUILD_LDFLAGS定义在<a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/Makefile#L431">Makefile - <em>KBUILD_LDFLAGS</em></a>，在<a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/arch/arm/Makefile#L51">Makefile - arch&#x2F;arm&#x2F;Makefile - <em>KBUILD_LDFLAGS</em></a>中有追加，最终它的值为-EL。</li>
<li>LDFLAGS_vmlinux的值由顶层 <a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/Makefile#L400">Makefile</a> 和 <a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/arch/arm/Makefile#L13">Makefile - arch&#x2F;arm&#x2F;Makefile</a> 这两个文件共同决定。</li>
</ul>
<p>其实这个地方由于涉及的地方较多，我们可以加个打印信息，这个 <a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/arch/arm/Makefile#L13">Makefile - arch&#x2F;arm&#x2F;Makefile</a> 文件在<a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/Makefile#L527">Makefile</a>中被调用，LDFLAGS_vmlinux在 <a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/Makefile#L985">Makefile - <em>LDFLAGS_vmlinux</em></a> 这里被导出，我们可以加个打印信息看一下：</p>
<figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">echo <span class="string">&quot;LDFLAGS_vmlinux=<span class="variable">$(LDFLAGS_vmlinux)</span>&quot;</span></span><br><span class="line">+<span class="variable">$(<span class="built_in">call</span> if_changed,link-vmlinux)</span> </span><br></pre></td></tr></table></figure>

<p>然后我们执行以下命令：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">make V=0 ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- distclean</span><br><span class="line">make V=0 ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- imx_v6_v7_defconfig</span><br><span class="line">make V=1 ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- all -j16</span><br></pre></td></tr></table></figure>

<p>会看到以下输出信息。</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">LDFLAGS_vmlinux=-p --no-undefined -X --pic-veneer  --build-id</span><br></pre></td></tr></table></figure>

<ul>
<li>ARCH_POSTLINK定义在<a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/Makefile#L1012">Makefile - <em>ARCH_POSTLINK</em></a></li>
</ul>
<figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ARCH_POSTLINK := <span class="variable">$(<span class="built_in">wildcard</span> <span class="variable">$(srctree)</span>/arch/<span class="variable">$(SRCARCH)</span>/Makefile.postlink)</span></span><br></pre></td></tr></table></figure>

<p>srctree&#x3D;<code>.</code>，SRCARCH&#x3D;arm，所以这里就是.&#x2F;arch&#x2F;arm&#x2F;Makefile.postlink，这个应该是编译生成的文件吧，我也不是很清楚，我去使用V&#x3D;1参数编译了一下，没有在编译过程中发现这个文件，也没有在编译完成后在 .&#x2F;arch&#x2F;arm 目录下发现这个文件，所以这里这个ARCH_POSTLINK应该是为空。</p>
<ul>
<li><code>$@</code>就是目标文件vmlinux</li>
</ul>
<p>所以展开就是：</p>
<figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Final link of vmlinux with optional arch pass after final link</span></span><br><span class="line">cmd_link-vmlinux =                                                 \</span><br><span class="line">	/bin/bash scripts/link-vmlinux.sh -p --no-undefined -X --pic-veneer  --build-id; \</span><br><span class="line">	true</span><br></pre></td></tr></table></figure>

<h4 id="3-3-4-link-vmlinux-sh"><a href="#3-3-4-link-vmlinux-sh" class="headerlink" title="3.3.4 link-vmlinux.sh"></a><font size=3>3.3.4 link-vmlinux.sh</font></h4><p>我们来看一下这个脚本，它在 <a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/scripts/link-vmlinux.sh">link-vmlinux.sh - scripts&#x2F;link-vmlinux.sh</a>：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">Link of vmlinux</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash"><span class="variable">$&#123;1&#125;</span> - optional extra .o files</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash"><span class="variable">$&#123;2&#125;</span> - output file</span></span><br><span class="line">vmlinux_link()</span><br><span class="line">&#123;</span><br><span class="line">	local lds=&quot;$&#123;objtree&#125;/$&#123;KBUILD_LDS&#125;&quot;</span><br><span class="line">	local objects</span><br><span class="line"></span><br><span class="line">	if [ &quot;$&#123;SRCARCH&#125;&quot; != &quot;um&quot; ]; then</span><br><span class="line">		objects=&quot;--whole-archive			\</span><br><span class="line">			built-in.a				\</span><br><span class="line">			--no-whole-archive			\</span><br><span class="line">			--start-group				\</span><br><span class="line"><span class="meta prompt_">			$</span><span class="language-bash">&#123;KBUILD_VMLINUX_LIBS&#125;			\</span></span><br><span class="line"><span class="language-bash">			--end-group				\</span></span><br><span class="line"><span class="language-bash">			<span class="variable">$&#123;1&#125;</span><span class="string">&quot;</span></span></span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_">		$</span><span class="language-bash"><span class="string">&#123;LD&#125; <span class="variable">$&#123;KBUILD_LDFLAGS&#125;</span> <span class="variable">$&#123;LDFLAGS_vmlinux&#125;</span> -o <span class="variable">$&#123;2&#125;</span>	\</span></span></span><br><span class="line"><span class="string"><span class="language-bash">			-T <span class="variable">$&#123;lds&#125;</span> <span class="variable">$&#123;objects&#125;</span></span></span></span><br><span class="line">	else</span><br><span class="line">		objects=&quot;-Wl,--whole-archive			\</span><br><span class="line">			built-in.a				\</span><br><span class="line">			-Wl,--no-whole-archive			\</span><br><span class="line">			-Wl,--start-group			\</span><br><span class="line"><span class="meta prompt_">			$</span><span class="language-bash"><span class="string">&#123;KBUILD_VMLINUX_LIBS&#125;			\</span></span></span><br><span class="line"><span class="string"><span class="language-bash">			-Wl,--end-group				\</span></span></span><br><span class="line"><span class="string"><span class="language-bash">			<span class="variable">$&#123;1&#125;</span>&quot;</span></span></span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_">		$</span><span class="language-bash">&#123;CC&#125; <span class="variable">$&#123;CFLAGS_vmlinux&#125;</span> -o <span class="variable">$&#123;2&#125;</span>			\</span></span><br><span class="line"><span class="language-bash">			-Wl,-T,<span class="variable">$&#123;lds&#125;</span>				\</span></span><br><span class="line"><span class="language-bash">			<span class="variable">$&#123;objects&#125;</span>				\</span></span><br><span class="line"><span class="language-bash">			-lutil -lrt -lpthread</span></span><br><span class="line">		rm -f linux</span><br><span class="line">	fi</span><br><span class="line">&#125;</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">......</span></span><br><span class="line">info LD vmlinux</span><br><span class="line">vmlinux_link &quot;$&#123;kallsymso&#125;&quot; vmlinux</span><br></pre></td></tr></table></figure>

<p>vmliux_link 就是最终链接出 vmlinux 的函数。</p>
<ul>
<li><p>第 9 行判断 SRCARCH 是否等于“um”，如 果不相等的话就执行 20~34 行的代码。因为 SRCARCH&#x3D;arm，因此条件成立，执行10~19 行的代码。</p>
</li>
<li><p>第18 ~ 19行的代码就是我们之前的链接操作。链接脚本lds&#x3D; .&#x2F;arch&#x2F;arm&#x2F;kernel&#x2F;vmlinux.lds。需要链接的文件由变量 KBUILD_VMLINUX_INIT 和 KBUILD_VMLINUX_MAIN 来决定。</p>
</li>
</ul>
<p>KBUILD_VMLINUX_INIT定义在<a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/Makefile#L981">Makefile - <em>KBUILD_VMLINUX_INIT</em></a>：</p>
<figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">export</span> KBUILD_VMLINUX_INIT := $(head-y) $(init-y)</span><br></pre></td></tr></table></figure>

<p>KBUILD_VMLINUX_MAIN定义在<a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/Makefile#L982">Makefile - <em>KBUILD_VMLINUX_MAIN</em></a>：</p>
<figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">export</span> KBUILD_VMLINUX_MAIN := $(core-y) $(libs-y2) $(drivers-y) $(net-y) $(virt-y)</span><br></pre></td></tr></table></figure>

<p>前面基本已经分析过了，但 <code>$(virt-y)</code>这个刚才没分析，不过都是一样的道理。</p>
<ul>
<li>第 37 行调用 vmlinux_link 函数来链接出 vmlinux。</li>
</ul>
<h3 id="3-4-打印信息"><a href="#3-4-打印信息" class="headerlink" title="3.4 打印信息"></a><font size=3>3.4 打印信息</font></h3><p>上面分析了那么多，我们详细来看一下打印信息吧，我们添加个起始和结尾标记，方便查找：</p>
<figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="section">vmlinux: scripts/link-vmlinux.sh autoksyms_recursive $(vmlinux-deps) FORCE</span></span><br><span class="line">	echo <span class="string">&quot;========== vmlinux-start ==========&quot;</span></span><br><span class="line"><span class="keyword">ifdef</span> CONFIG_HEADERS_CHECK</span><br><span class="line">	<span class="variable">$(Q)</span><span class="variable">$(MAKE)</span> -f <span class="variable">$(srctree)</span>/Makefile headers_check</span><br><span class="line"><span class="keyword">endif</span></span><br><span class="line"><span class="keyword">ifdef</span> CONFIG_GDB_SCRIPTS</span><br><span class="line">	<span class="variable">$(Q)</span>ln -fsn <span class="variable">$(<span class="built_in">abspath</span> <span class="variable">$(srctree)</span>/scripts/gdb/vmlinux-gdb.py)</span></span><br><span class="line"><span class="keyword">endif</span></span><br><span class="line">	echo <span class="string">&quot;========== vmlinux-if_changed ==========&quot;</span></span><br><span class="line">	+<span class="variable">$(<span class="built_in">call</span> if_changed,link-vmlinux)</span></span><br><span class="line">	echo <span class="string">&quot;========== vmlinux-end ==========&quot;</span></span><br></pre></td></tr></table></figure>

<p>然后我们执行以下命令：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">make V=0 ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- distclean</span><br><span class="line">make V=0 ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- imx_v6_v7_defconfig</span><br><span class="line">make V=1 ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- all -j16</span><br></pre></td></tr></table></figure>

<p>然后就可以看到打印信息中这个vmlinux规则都在做些什么，这里是一些简化后的重要打印信息：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line">echo &quot;========== vmlinux-start ==========&quot;</span><br><span class="line">========== vmlinux-start ==========</span><br><span class="line">echo &quot;========== vmlinux-if_changed ==========&quot;</span><br><span class="line">========== vmlinux-if_changed ==========</span><br><span class="line">  /bin/sh scripts/link-vmlinux.sh arm-linux-gnueabihf-ld  -EL -p --no-undefined -X --pic-veneer  --build-id ;  true</span><br><span class="line">+ &#x27;[&#x27; arm-linux-gnueabihf-ld = clean &#x27;]&#x27;</span><br><span class="line">+ case &quot;$&#123;KCONFIG_CONFIG&#125;&quot; in</span><br><span class="line">+ . ./.config</span><br><span class="line">++ CONFIG_CC_IS_GCC=y</span><br><span class="line">++ CONFIG_GCC_VERSION=40902</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">中间部分省略......</span></span><br><span class="line"></span><br><span class="line">+ local objects</span><br><span class="line">+ &#x27;[&#x27; arm &#x27;!=&#x27; um &#x27;]&#x27;</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">中间部分省略......</span></span><br><span class="line">+ arm-linux-gnueabihf-ld -EL -p --no-undefined -X --pic-veneer --build-id -o vmlinux -T ./arch/arm/kernel/vmlinux.lds --whole-archive built-in.a --no-whole-archive --start-group arch/arm/lib/lib.a lib/lib.a --end-group .tmp_kallsyms2.o</span><br><span class="line">+ &#x27;[&#x27; -n y &#x27;]&#x27;</span><br><span class="line">+ info SORTEX vmlinux</span><br><span class="line">+ &#x27;[&#x27; &#x27;&#x27; &#x27;!=&#x27; silent_ &#x27;]&#x27;</span><br><span class="line">+ printf &#x27;  %-7s %s\n&#x27; SORTEX vmlinux</span><br><span class="line">  SORTEX  vmlinux</span><br><span class="line">+ sortextable vmlinux</span><br><span class="line">+ ./scripts/sortextable vmlinux</span><br><span class="line">+ info SYSMAP System.map</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">中间部分省略......</span></span><br><span class="line">echo &quot;========== vmlinux-end ==========&quot;</span><br><span class="line">========== vmlinux-end ==========</span><br></pre></td></tr></table></figure>

<p>从这里看，前面分析的一些变量的值都是正确的。</p>
<h2 id="4-built-in-a生成过程"><a href="#4-built-in-a生成过程" class="headerlink" title="4. built-in.a生成过程"></a><font size=3>4. built-in.a生成过程</font></h2><h3 id="4-1-vmlinux-deps变量"><a href="#4-1-vmlinux-deps变量" class="headerlink" title="4.1 vmlinux-deps变量"></a><font size=3>4.1 vmlinux-deps变量</font></h3><p>前面在分析<a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/Makefile#L1019">Makefile - <em>vmlinux</em></a>的时候：</p>
<figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="section">vmlinux: scripts/link-vmlinux.sh autoksyms_recursive $(vmlinux-deps) FORCE</span></span><br><span class="line"><span class="keyword">ifdef</span> CONFIG_HEADERS_CHECK</span><br><span class="line">	<span class="variable">$(Q)</span><span class="variable">$(MAKE)</span> -f <span class="variable">$(srctree)</span>/Makefile headers_check</span><br><span class="line"><span class="keyword">endif</span></span><br><span class="line"><span class="keyword">ifdef</span> CONFIG_GDB_SCRIPTS</span><br><span class="line">	<span class="variable">$(Q)</span>ln -fsn <span class="variable">$(<span class="built_in">abspath</span> <span class="variable">$(srctree)</span>/scripts/gdb/vmlinux-gdb.py)</span></span><br><span class="line"><span class="keyword">endif</span></span><br><span class="line">	+<span class="variable">$(<span class="built_in">call</span> if_changed,link-vmlinux)</span></span><br></pre></td></tr></table></figure>

<p>vmlinux是依赖vmlinux-deps的，而vmlinux-deps定义在 <a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/Makefile#L989">Makefile - <em>vmlinux-deps</em></a> ：</p>
<figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">vmlinux-deps := <span class="variable">$(KBUILD_LDS)</span> <span class="variable">$(KBUILD_VMLINUX_INIT)</span> <span class="variable">$(KBUILD_VMLINUX_MAIN)</span> <span class="variable">$(KBUILD_VMLINUX_LIBS)</span></span><br></pre></td></tr></table></figure>

<p>这几个变量都定义 <a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/Makefile#L980">Makefile - <em>Externally visible symbols</em></a>：</p>
<figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Externally visible symbols (used by link-vmlinux.sh)</span></span><br><span class="line"><span class="keyword">export</span> KBUILD_VMLINUX_INIT := $(head-y) $(init-y)</span><br><span class="line"><span class="keyword">export</span> KBUILD_VMLINUX_MAIN := $(core-y) $(libs-y2) $(drivers-y) $(net-y) $(virt-y)</span><br><span class="line"><span class="keyword">export</span> KBUILD_VMLINUX_LIBS := $(libs-y1)</span><br><span class="line"><span class="keyword">export</span> KBUILD_LDS          := arch/<span class="variable">$(SRCARCH)</span>/kernel/vmlinux.lds</span><br></pre></td></tr></table></figure>

<p>上面些我们前面都分析过了，他们最终是一系列的<code>built-in.a</code>文件。我们可以加个打印信息看一眼：</p>
<figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="section">vmlinux: scripts/link-vmlinux.sh autoksyms_recursive $(vmlinux-deps) FORCE</span></span><br><span class="line">	@echo <span class="string">&quot;vmlinux-deps=$(vmlinux-deps)&quot;</span></span><br><span class="line"><span class="keyword">ifdef</span> CONFIG_HEADERS_CHECK</span><br><span class="line">	<span class="variable">$(Q)</span><span class="variable">$(MAKE)</span> -f <span class="variable">$(srctree)</span>/Makefile headers_check</span><br><span class="line"><span class="keyword">endif</span></span><br><span class="line"><span class="keyword">ifdef</span> CONFIG_GDB_SCRIPTS</span><br><span class="line">	<span class="variable">$(Q)</span>ln -fsn <span class="variable">$(<span class="built_in">abspath</span> <span class="variable">$(srctree)</span>/scripts/gdb/vmlinux-gdb.py)</span></span><br><span class="line"><span class="keyword">endif</span></span><br><span class="line">	+<span class="variable">$(<span class="built_in">call</span> if_changed,link-vmlinux)</span></span><br></pre></td></tr></table></figure>

<p>然后我们执行以下命令：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">make V=0 ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- distclean</span><br><span class="line">make V=0 ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- imx_v6_v7_defconfig</span><br><span class="line">make V=1 ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- all -j16</span><br></pre></td></tr></table></figure>

<p>可以看到有如下打印信息：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">vmlinux-deps=arch/arm/kernel/vmlinux.lds arch/arm/kernel/head.o  init/built-in.a  usr/built-in.a  arch/arm/vfp/built-in.a  arch/arm/vdso/built-in.a  arch/arm/kernel/built-in.a  arch/arm/mm/built-in.a  arch/arm/common/built-in.a  arch/arm/probes/built-in.a  arch/arm/net/built-in.a  arch/arm/crypto/built-in.a  arch/arm/firmware/built-in.a  arch/arm/mach-imx/built-in.a  kernel/built-in.a  certs/built-in.a  mm/built-in.a  fs/built-in.a  ipc/built-in.a  security/built-in.a  crypto/built-in.a  block/built-in.a  arch/arm/lib/built-in.a  lib/built-in.a  drivers/built-in.a  sound/built-in.a  firmware/built-in.a  net/built-in.a  virt/built-in.a  arch/arm/lib/lib.a  lib/lib.a</span><br></pre></td></tr></table></figure>

<p>除了 arch&#x2F;arm&#x2F;kernel&#x2F;vmlinux.lds 以外，其他都是要编译链接生成的。</p>
<h3 id="4-2-vmlinux-deps的依赖"><a href="#4-2-vmlinux-deps的依赖" class="headerlink" title="4.2 vmlinux-deps的依赖"></a><font size=3>4.2 vmlinux-deps的依赖</font></h3><p>我们继续往下看vmlinux-deps，会看到</p>
<figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># The actual objects are generated when descending,</span></span><br><span class="line"><span class="comment"># make sure no implicit rule kicks in</span></span><br><span class="line"><span class="variable">$(<span class="built_in">sort</span> $(vmlinux-deps)</span>): $(vmlinux-dirs) ;</span><br></pre></td></tr></table></figure>

<p>sort函数就是用来排序的，它一般格式如下：</p>
<figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="variable">$(<span class="built_in">sort</span> &lt;list&gt;)</span></span><br></pre></td></tr></table></figure>

<p>给字符串 list 中的单词排序（升序），会返回排序后的字符串。另外sort函数会去掉 list  中相同的单词。另外可以看出 vmlinux-deps 依赖 vmlinux-dirs。</p>
<h3 id="4-3-vmlinux-dirs变量"><a href="#4-3-vmlinux-dirs变量" class="headerlink" title="4.3 vmlinux-dirs变量"></a><font size=3>4.3 vmlinux-dirs变量</font></h3><p>vmlinux-dirs 也定义在顶层 <a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/Makefile#L965">Makefile - <em>vmlinux-dirs</em></a>：</p>
<figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">vmlinux-dirs	:= <span class="variable">$(<span class="built_in">patsubst</span> %/,%,$(<span class="built_in">filter</span> %/, $(init-y)</span> $(init-m) \</span><br><span class="line">		     $(core-y) $(core-m) $(drivers-y) $(drivers-m) \</span><br><span class="line">		     $(net-y) $(net-m) $(libs-y) $(libs-m) $(virt-y)))</span><br><span class="line">		     </span><br><span class="line"><span class="comment"># ......</span></span><br><span class="line"><span class="comment"># Build samples along the rest of the kernel. This needs headers_install.</span></span><br><span class="line"><span class="keyword">ifdef</span> CONFIG_SAMPLES</span><br><span class="line">vmlinux-dirs += samples</span><br><span class="line"><span class="section">samples: headers_install</span></span><br><span class="line"><span class="keyword">endif</span></span><br></pre></td></tr></table></figure>

<p>vmlinux-dirs 看名字就知道和目录有关，此变量保存着生成 vmlinux 所需源码文件的目录。这里不分析了，直接添加打印信息吧，还是在这个vmlinux目标这里加：</p>
<figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="section">vmlinux: scripts/link-vmlinux.sh autoksyms_recursive $(vmlinux-deps) FORCE</span></span><br><span class="line">	@echo <span class="string">&quot;vmlinux-dirs=$(vmlinux-dirs)&quot;</span></span><br><span class="line"><span class="keyword">ifdef</span> CONFIG_HEADERS_CHECK</span><br><span class="line">	<span class="variable">$(Q)</span><span class="variable">$(MAKE)</span> -f <span class="variable">$(srctree)</span>/Makefile headers_check</span><br><span class="line"><span class="keyword">endif</span></span><br><span class="line"><span class="keyword">ifdef</span> CONFIG_GDB_SCRIPTS</span><br><span class="line">	<span class="variable">$(Q)</span>ln -fsn <span class="variable">$(<span class="built_in">abspath</span> <span class="variable">$(srctree)</span>/scripts/gdb/vmlinux-gdb.py)</span></span><br><span class="line"><span class="keyword">endif</span></span><br><span class="line">	+<span class="variable">$(<span class="built_in">call</span> if_changed,link-vmlinux)</span></span><br></pre></td></tr></table></figure>

<p>和前面一样，我们编译一遍，会得到如下打印信息：</p>
<figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">vmlinux-dirs=init usr arch/arm/vfp arch/arm/vdso arch/arm/kernel arch/arm/mm arch/arm/common arch/arm/probes arch/arm/net arch/arm/crypto arch/arm/firmware arch/arm/mach-imx kernel certs mm fs ipc security crypto block drivers sound firmware net arch/arm/lib lib virt</span><br></pre></td></tr></table></figure>

<h3 id="4-4-vmlinux-dirs的依赖"><a href="#4-4-vmlinux-dirs的依赖" class="headerlink" title="4.4 vmlinux-dirs的依赖"></a><font size=3>4.4 vmlinux-dirs的依赖</font></h3><h4 id="4-4-1-规则展开"><a href="#4-4-1-规则展开" class="headerlink" title="4.4.1 规则展开"></a><font size=3>4.4.1 规则展开</font></h4><p>我们继续往后看，会看到vmlinux-dirs也是有依赖的，它定义在<a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/Makefile#L1045">Makefile - <em>vmlinux-dirs</em></a>：</p>
<figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Handle descending into subdirectories listed in $(vmlinux-dirs)</span></span><br><span class="line"><span class="comment"># Preset locale variables to speed up the build process. Limit locale</span></span><br><span class="line"><span class="comment"># tweaks to this spot to avoid wrong language settings when running</span></span><br><span class="line"><span class="comment"># make menuconfig etc.</span></span><br><span class="line"><span class="comment"># Error messages still appears in the original language</span></span><br><span class="line"></span><br><span class="line">PHONY += $(vmlinux-dirs)</span><br><span class="line"><span class="section">$(vmlinux-dirs): prepare scripts</span></span><br><span class="line">	<span class="variable">$(Q)</span><span class="variable">$(MAKE)</span> <span class="variable">$(build)</span>=<span class="variable">$@</span> need-builtin=1</span><br></pre></td></tr></table></figure>

<p>目标 vmlinux-dirs 依赖 prepare 和 scripts 。这两个依赖就暂时不去详细了解了。我们重点看一下第9行的命令。build前面已经说过了，它定义在<a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/scripts/Kbuild.include#L184">Kbuild.include - scripts&#x2F;Kbuild.include - <em>build</em></a>，值为” -f .&#x2F;scripts&#x2F;Makefile.build obj “，所以这一行命令展开就是：</p>
<figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">@make -f ./scripts/Makefile.build obj=<span class="variable">$@</span> need-builtin=1</span><br></pre></td></tr></table></figure>

<p><code>$@</code>表示目标文件，也就是 vmlinux-dirs 的值，将 vmlinux-dirs 中的这些目录全部带入到命令中，结果如下：  </p>
<figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line">@make -f ./scripts/Makefile.build obj=init need-builtin=1</span><br><span class="line">@make -f ./scripts/Makefile.build obj=usr need-builtin=1</span><br><span class="line">@make -f ./scripts/Makefile.build obj=arch/arm/vfp need-builtin=1</span><br><span class="line">@make -f ./scripts/Makefile.build obj=arch/arm/vdso need-builtin=1</span><br><span class="line">@make -f ./scripts/Makefile.build obj=arch/arm/kernel need-builtin=1</span><br><span class="line">@make -f ./scripts/Makefile.build obj=arch/arm/mm need-builtin=1</span><br><span class="line">@make -f ./scripts/Makefile.build obj=arch/arm/common need-builtin=1</span><br><span class="line">@make -f ./scripts/Makefile.build obj=arch/arm/probes need-builtin=1</span><br><span class="line">@make -f ./scripts/Makefile.build obj=arch/arm/net need-builtin=1</span><br><span class="line">@make -f ./scripts/Makefile.build obj=arch/arm/crypto need-builtin=1</span><br><span class="line">@make -f ./scripts/Makefile.build obj=arch/arm/firmware need-builtin=1</span><br><span class="line">@make -f ./scripts/Makefile.build obj=arch/arm/mach-imx need-builtin=1</span><br><span class="line">@make -f ./scripts/Makefile.build obj=kernel need-builtin=1</span><br><span class="line">@make -f ./scripts/Makefile.build obj=certs need-builtin=1</span><br><span class="line">@make -f ./scripts/Makefile.build obj=mm need-builtin=1</span><br><span class="line">@make -f ./scripts/Makefile.build obj=fs need-builtin=1</span><br><span class="line">@make -f ./scripts/Makefile.build obj=ipc need-builtin=1</span><br><span class="line">@make -f ./scripts/Makefile.build obj=security need-builtin=1</span><br><span class="line">@make -f ./scripts/Makefile.build obj=crypto need-builtin=1</span><br><span class="line">@make -f ./scripts/Makefile.build obj=block need-builtin=1</span><br><span class="line">@make -f ./scripts/Makefile.build obj=drivers need-builtin=1</span><br><span class="line">@make -f ./scripts/Makefile.build obj=sound need-builtin=1</span><br><span class="line">@make -f ./scripts/Makefile.build obj=firmware need-builtin=1</span><br><span class="line">@make -f ./scripts/Makefile.build obj=net need-builtin=1</span><br><span class="line">@make -f ./scripts/Makefile.build obj=arch/arm/lib need-builtin=1</span><br><span class="line">@make -f ./scripts/Makefile.build obj=lib need-builtin=1</span><br><span class="line">@make -f ./scripts/Makefile.build obj=virt need-builtin=1</span><br></pre></td></tr></table></figure>

<p>这些命令运行过程其实都是一样的，我们就以“@ make -f .&#x2F;scripts&#x2F;Makefile.build obj&#x3D;init need-builtin&#x3D;1”这个命令为例 来分析一下。</p>
<h4 id="4-4-2-命令分析"><a href="#4-4-2-命令分析" class="headerlink" title="4.4.2 命令分析"></a><font size=3>4.4.2 命令分析</font></h4><p>我们先看这个 <a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/scripts/Makefile.build#L80">Makefile.build - scripts&#x2F;Makefile.build</a>中的默认目标__build：</p>
<figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="section">__build: $(if <span class="variable">$(KBUILD_BUILTIN)</span>,$(builtin-target) $(lib-target) $(extra-y)) \</span></span><br><span class="line">	 <span class="variable">$(<span class="built_in">if</span> <span class="variable">$(KBUILD_MODULES)</span>,$(obj-m)</span> $(modorder-target)) \</span><br><span class="line">	 $(subdir-ym) <span class="variable">$(always)</span></span><br><span class="line">	@:</span><br></pre></td></tr></table></figure>

<p>当只编译 Linux 内核镜像文件，也就是使用“ make zImage ” 编译的时候，KBUILD_BUILTIN&#x3D;1， KBUILD_MODULES 为空。“make”命令是会编译所有的东西，包括 Linux 内核镜像文件和一些模块文件。我们这里简单一点，如果只编译 Linux 内核镜像的话， __build 目标简化为：  </p>
<figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="section">__build: $(builtin-target) $(lib-target) $(extra-y)) $(subdir-ym) <span class="variable">$(always)</span></span></span><br><span class="line">	@:</span><br></pre></td></tr></table></figure>

<p>重点来看一下 builtin-target 这个依赖， builtin-target 同样定义在文件 <a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/scripts/Makefile.build#L72">Makefile.build - scripts&#x2F;Makefile.build - <em>builtin-target</em></a> 中  ：</p>
<figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">ifneq</span> (<span class="variable">$(<span class="built_in">strip</span> $(real-obj-y)</span> $(need-builtin)),)</span><br><span class="line">builtin-target := <span class="variable">$(obj)</span>/built-in.a</span><br><span class="line"><span class="keyword">endif</span></span><br></pre></td></tr></table></figure>

<p>第2行就是 builtin-target 变量的值，为<code>$(obj)/built-in.a</code>，这就是这些 built-in.a 的来源了。要生成 built-in.a，要求real-obj-y 和need-builtin 变量不能全部为空。我们以这条命令为例：</p>
<figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">@make -f ./scripts/Makefile.build obj=init need-builtin=1</span><br></pre></td></tr></table></figure>

<p>可以看到这里obj&#x3D;init，need-builtin&#x3D;1，所以上面的builtin-target可以展开一下：</p>
<figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">ifneq</span> (<span class="variable">$(<span class="built_in">strip</span> $(real-obj-y)</span> 1),)</span><br><span class="line">builtin-target := init/built-in.a</span><br><span class="line"><span class="keyword">endif</span></span><br></pre></td></tr></table></figure>

<p>那 built-in.a 是怎么生成的？我们继续看这个builtin-target，在文件 <a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/scripts/Makefile.build#L445">Makefile.build - scripts&#x2F;Makefile.build</a> 中有如下代码：  </p>
<figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#</span></span><br><span class="line"><span class="comment"># Rule to compile a set of .o files into one .o file</span></span><br><span class="line"><span class="comment">#</span></span><br><span class="line"><span class="keyword">ifdef</span> builtin-target</span><br><span class="line"></span><br><span class="line"><span class="comment"># built-in.a archives are made with no symbol table or index which</span></span><br><span class="line"><span class="comment"># makes them small and fast, but unable to be used by the linker.</span></span><br><span class="line"><span class="comment"># scripts/link-vmlinux.sh builds an aggregate built-in.a with a symbol</span></span><br><span class="line"><span class="comment"># table and index.</span></span><br><span class="line">quiet_cmd_ar_builtin = AR      <span class="variable">$@</span></span><br><span class="line">      cmd_ar_builtin = rm -f <span class="variable">$@</span>; \</span><br><span class="line">                     <span class="variable">$(AR)</span> rcSTP<span class="variable">$(KBUILD_ARFLAGS)</span> <span class="variable">$@</span> <span class="variable">$(<span class="built_in">filter</span> $(real-obj-y)</span>, <span class="variable">$^</span>)</span><br><span class="line"></span><br><span class="line"><span class="section">$(builtin-target): $(real-obj-y) FORCE</span></span><br><span class="line">	<span class="variable">$(<span class="built_in">call</span> if_changed,ar_builtin)</span></span><br><span class="line"></span><br><span class="line">targets += $(builtin-target)</span><br><span class="line"><span class="keyword">endif</span> <span class="comment"># builtin-target</span></span><br></pre></td></tr></table></figure>

<p>可以看到第14行，目标就是 builtin-target，依赖为 real-obj-y，命令为“<code>$(call if_changed,ar_builtin)</code>”，前面我们分析过这个if_changed函数，这里参数为 ar_builtin，其返回值就是具体的命令。 我们可以放到这里再看一下 <a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/scripts/Kbuild.include#L259">Kbuild.include - scripts&#x2F;Kbuild.include - <em>if_changed</em></a> ：</p>
<figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Execute command if command has changed or prerequisite(s) are updated.</span></span><br><span class="line">if_changed = <span class="variable">$(<span class="built_in">if</span> $(<span class="built_in">strip</span> $(any-prereq)</span> $(arg-check)),                       \</span><br><span class="line">	@set -e;                                                             \</span><br><span class="line">	$(echo-cmd) $(cmd_$(1));                                             \</span><br><span class="line">	printf &#x27;%s\n&#x27; &#x27;cmd_<span class="variable">$@</span> := $(make-cmd)&#x27; &gt; $(dot-target).cmd, @:)</span><br></pre></td></tr></table></figure>

<p>它会调用 <code>cmd_$(1)</code>所对应的命令(<code>$(1)</code>就是函数的第 1 个参数)，在这里就是调用 cmd_ar_builtin 所对应的命令。这里面的命令就是使用AR工具生成<code>.a</code>文件</p>
<h3 id="4-5-打印信息"><a href="#4-5-打印信息" class="headerlink" title="4.5 打印信息"></a><font size=3>4.5 打印信息</font></h3><p>我们在终端执行：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">make V=0 ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- distclean</span><br><span class="line">make V=0 ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- imx_v6_v7_defconfig</span><br><span class="line">make V=1 ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- all -j16</span><br></pre></td></tr></table></figure>

<p>然后我们会看到以下打印信息：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">rm -f init/built-in.a; arm-linux-gnueabihf-ar rcSTPD init/built-in.a init/main.o init/version.o init/do_mounts.o init/do_mounts_rd.o init/do_mounts_initrd.o init/initramfs.o init/calibrate.o init/init_task.o</span><br></pre></td></tr></table></figure>

<p>这个就是最后将相关的.o链接在一起生成的init&#x2F;built-in.a文件的打印信息。命令 <code>arm-linux-gnueabihf-ar rcSTPD</code> 中，<code>rcSTPD</code> 是一系列选项的组合，用于指定 <code>arm-linux-gnueabihf-ar</code> 工具的操作模式。下面是每个选项的含义：</p>
<ul>
<li><code>r</code>：替换。如果指定的库文件中已经存在要添加的文件，则替换它。</li>
<li><code>c</code>：创建。创建一个新的库文件。如果指定的库文件不存在，则创建它；如果已存在，则根据其他选项（如 <code>r</code>）更新它。</li>
<li><code>S</code>：创建索引。为库文件创建一个目标文件索引，这可以加快之后链接时库文件的搜索速度。</li>
<li><code>T</code>：使用给定的文件名作为库文件的临时索引文件。通常，这个选项后面会跟着一个文件名。但在你提供的命令中，<code>T</code> 后面没有直接跟随文件名，这可能是一个错误或者遗漏，或者是在特定上下文中有特殊用法。</li>
<li><code>P</code>：保留路径。在将文件添加到库中时，保留文件的路径信息。默认情况下，<code>ar</code> 工具会将文件路径剥离，只保留文件名。使用 <code>P</code> 选项可以保留完整的路径。</li>
<li><code>D</code>：通常 <code>D</code> 选项用于删除库中的文件。这里提及是为了完整性，因为 <code>D</code> 是 <code>ar</code> 工具的一个常用选项。</li>
</ul>
<h1 id="四、make-zImage"><a href="#四、make-zImage" class="headerlink" title="四、make zImage"></a><font size=3>四、make zImage</font></h1><h2 id="1-vmlinux、-Image，-zImage、-uImage-的区别"><a href="#1-vmlinux、-Image，-zImage、-uImage-的区别" class="headerlink" title="1. vmlinux、 Image， zImage、 uImage 的区别  "></a><font size=3>1. vmlinux、 Image， zImage、 uImage 的区别  </font></h2><p>其实前面已经大概了解过了：</p>
<ul>
<li>vmlinux 是编译出来的最原始的 ELF格式内核文件，是未压缩的。</li>
<li>Image 是 Linux 内核镜像文件，但是 Image 仅包含可执行的二进制数据。 Image 就是使用 objcopy 取消掉 vmlinux 中的一些其他信息，比如符号表什么的。但是 Image 是没有压缩过的， Image 保存在 arch&#x2F;arm&#x2F;boot 目录下 。</li>
<li>zImage 是经过 gzip 压缩后的 Image 。</li>
<li>uImage 是老版本 uboot 专用的镜像文件， uImag 是在 zImage 前面加了一个长度为 64字节的“头”，这个头信息描述了该镜像文件的类型、加载位置、生成时间、大小等信息。但是新的 uboot 已经支持了 zImage 启动！所以已经很少用到 uImage 了，除非我们用的很古老的 uboot。</li>
</ul>
<p>所以一般我们还是使用zImage这个镜像文件。</p>
<h2 id="2-zImage"><a href="#2-zImage" class="headerlink" title="2. zImage"></a><font size=3>2. zImage</font></h2><p>使用“ make”、“ make all”、“ make zImage”这些命令都可以编译出 zImage 镜像，  我们来看一下 BOOT_TARGETS  变量，它定义在<a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/arch/arm/Makefile#L327">Makefile - arch&#x2F;arm&#x2F;Makefile - <em>BOOT_TARGETS</em></a>：</p>
<figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">BOOT_TARGETS	= zImage Image xipImage bootpImage uImage</span><br><span class="line">INSTALL_TARGETS	= zinstall uinstall install</span><br><span class="line"></span><br><span class="line">PHONY += bzImage <span class="variable">$(BOOT_TARGETS)</span> <span class="variable">$(INSTALL_TARGETS)</span></span><br><span class="line"></span><br><span class="line">bootpImage uImage: zImage</span><br><span class="line"><span class="section">zImage: Image</span></span><br><span class="line"></span><br><span class="line"><span class="variable">$(BOOT_TARGETS)</span>: vmlinux</span><br><span class="line">	<span class="variable">$(Q)</span><span class="variable">$(MAKE)</span> <span class="variable">$(build)</span>=<span class="variable">$(boot)</span> MACHINE=<span class="variable">$(MACHINE)</span> <span class="variable">$(boot)</span>/<span class="variable">$@</span></span><br><span class="line">	@<span class="variable">$(kecho)</span> &#x27;  Kernel: <span class="variable">$(boot)</span>/<span class="variable">$@</span> is ready&#x27;</span><br></pre></td></tr></table></figure>

<p>第 1 行。变量 BOOT_TARGETS 包含 zImage， Image， xipImage 等镜像文件。</p>
<p>第 9 行， BOOT_TARGETS 依赖 vmlinux，因此如果使用“make zImage”编译的 Linux 内核的话，首先肯定要先编译出 vmlinux。  </p>
<p>第 10 行，具体的命令，比如要编译 zImage，那么命令展开以后如下所示：  </p>
<figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">@ make -f ./scripts/Makefile.build obj=arch/arm/boot MACHINE=arch/arm/boot/zImage</span><br></pre></td></tr></table></figure>

<p>和前面一样，都是使用scripts&#x2F;Makefile.build完成vmlinux到zImage的转换。</p>

    </div>

    
    
    

    <footer class="post-footer">




    <div>
        
            <div style="text-align:center;color: #ccc;font-size:14px;">
            ----------本文结束
            <i class="fas fa-fan fa-spin" style="color: #FF1493; font-size: 1rem"></i>
            感谢您的阅读----------
            </div>
        
    </div>





  
  <div class="my_post_copyright"> 
    <p><span>文章标题:</span><a href="/post/2aa70834.html">LV05-03-Kernel-03-01-顶层Makefile基础解析</a></p>
    <p><span>文章作者:</span><a href="/" title="欢迎访问 《苏木》 的学习笔记">苏木</a></p>
    <p><span>发布时间:</span>2024年11月27日 - 07:53</p>
    <p><span>最后更新:</span>2025年06月14日 - 00:25</p>
    <p><span>原始链接:</span><a href="/post/2aa70834.html" title="LV05-03-Kernel-03-01-顶层Makefile基础解析">https://sumumm.github.io/post/2aa70834.html</a></p>
    <p><span>许可协议:</span><i class="fab fa-creative-commons"></i> <a rel="license" href= "https://creativecommons.org/licenses/by-nc-nd/4.0/" target="_blank" title="Attribution-NonCommercial-NoDerivatives 4.0 International (CC BY-NC-ND 4.0)">署名-非商业性使用-禁止演绎 4.0 国际</a> 转载请保留原文链接及作者。</p>  
  </div>
  


          <div class="post-tags">
              <a href="/tags/LV05-%E7%B3%BB%E7%BB%9F%E9%95%9C%E5%83%8F/" rel="tag"><i class="fa fa-tag"></i> LV05-系统镜像</a>
          </div>

        

          <div class="post-nav">
            <div class="post-nav-item">
                <a href="/post/5d81934f.html" rel="prev" title="LV05-03-Kernel-03-02-make-single-module">
                  <i class="fa fa-angle-left"></i> LV05-03-Kernel-03-02-make-single-module
                </a>
            </div>
            <div class="post-nav-item">
                <a href="/post/620e325b.html" rel="next" title="LV06-02-内核模块-08-内核模块符号导出">
                  LV06-02-内核模块-08-内核模块符号导出 <i class="fa fa-angle-right"></i>
                </a>
            </div>
          </div>
    </footer>
  </article>
</div>






</div>
  </main>

  <footer class="footer">
    <div class="footer-inner">

  <div class="copyright">
    &copy; 2017 – 
    <span itemprop="copyrightYear">2025</span>
    <span class="with-love">
      <i class="fa fa-heart"></i>
    </span>
    <span class="author" itemprop="copyrightHolder">苏木</span>
  </div>
<div class="wordcount">
  <span class="post-meta-item">
    <span class="post-meta-item-icon">
      <i class="fa fa-chart-line"></i>
    </span>
      <span>站点总字数：</span>
    <span title="站点总字数">3.7m</span>
  </span>
  <span class="post-meta-item">
    <span class="post-meta-item-icon">
      <i class="fa fa-coffee"></i>
    </span>
      <span>站点阅读时长 &asymp;</span>
    <span title="站点阅读时长">225:26</span>
  </span>
</div>




    <span id="sitetime"></span>
    <script defer language=javascript>
        function siteTime()
        {
            window.setTimeout("siteTime()", 1000);
            var seconds = 1000;
            var minutes = seconds * 60;
            var hours = minutes * 60;
            var days = hours * 24;
            var years = days * 365;
            var today = new Date();
            var todayYear = today.getFullYear();
            var todayMonth = today.getMonth()+1;
            var todayDate = today.getDate();
            var todayHour = today.getHours();
            var todayMinute = today.getMinutes();
            var todaySecond = today.getSeconds();
            /*==================================================
            Date.UTC() -- 返回date对象距世界标准时间(UTC)1970年1月1日午夜之间的毫秒数(时间戳)
            year        - 作为date对象的年份，为4位年份值
            month       - 0-11之间的整数，做为date对象的月份
            day         - 1-31之间的整数，做为date对象的天数
            hours       - 0(午夜24点)-23之间的整数，做为date对象的小时数
            minutes     - 0-59之间的整数，做为date对象的分钟数
            seconds     - 0-59之间的整数，做为date对象的秒数
            microseconds - 0-999之间的整数，做为date对象的毫秒数
            ==================================================*/
            var t1 = Date.UTC(2017, 
                              5, 
                              19, 
                              0, 
                              0, 
                              0); //北京时间
            var t2 = Date.UTC(todayYear,todayMonth,todayDate,todayHour,todayMinute,todaySecond);
            var diff = t2-t1;
            var diffYears = Math.floor(diff/years);
            var diffDays = Math.floor((diff/days)-diffYears*365);
            var diffHours = Math.floor((diff-(diffYears*365+diffDays)*days)/hours);
            var diffMinutes = Math.floor((diff-(diffYears*365+diffDays)*days-diffHours*hours)/minutes);
            var diffSeconds = Math.floor((diff-(diffYears*365+diffDays)*days-diffHours*hours-diffMinutes*minutes)/seconds);
            document.getElementById("sitetime").innerHTML="已在这里 "+diffYears+" 年 "+diffDays+" 天 "+diffHours+" 小时 "+diffMinutes+" 分钟 "+diffSeconds+" 秒";
        }
        siteTime();
    </script>



    </div>
  </footer>

  
  <div class="back-to-top" role="button" aria-label="返回顶部">
    <i class="fa fa-arrow-up fa-lg"></i>
    <span>0%</span>
  </div>
  <div class="reading-progress-bar"></div>

<noscript>
  <div class="noscript-warning">Theme NexT works best with JavaScript enabled</div>
</noscript>


  
  <script src="https://cdnjs.cloudflare.com/ajax/libs/animejs/3.2.1/anime.min.js" integrity="sha256-XL2inqUJaslATFnHdJOi9GfQ60on8Wx1C2H8DYiN1xY=" crossorigin="anonymous"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/next-theme-pjax/0.6.0/pjax.min.js" integrity="sha256-vxLn1tSKWD4dqbMRyv940UYw4sXgMtYcK6reefzZrao=" crossorigin="anonymous"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/fancyapps-ui/5.0.28/fancybox/fancybox.umd.js" integrity="sha256-ytMJGN3toR+a84u7g7NuHm91VIR06Q41kMWDr2pq7Zo=" crossorigin="anonymous"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/lozad.js/1.16.0/lozad.min.js" integrity="sha256-mOFREFhqmHeQbXpK2lp4nA3qooVgACfh88fpJftLBbc=" crossorigin="anonymous"></script>
<script src="/js/comments.js"></script><script src="/js/utils.js"></script><script src="/js/motion.js"></script><script src="/js/next-boot.js"></script><script src="/js/pjax.js"></script>

  <script src="https://cdnjs.cloudflare.com/ajax/libs/hexo-generator-searchdb/1.4.1/search.js" integrity="sha256-1kfA5uHPf65M5cphT2dvymhkuyHPQp5A53EGZOnOLmc=" crossorigin="anonymous"></script>
<script src="/js/third-party/search/local-search.js"></script>




  <script src="/js/third-party/fancybox.js"></script>

  <script src="/js/third-party/pace.js"></script>


  




  

  <script class="next-config" data-name="enableMath" type="application/json">true</script><script class="next-config" data-name="mathjax" type="application/json">{"enable":true,"tags":"none","js":{"url":"https://cdnjs.cloudflare.com/ajax/libs/mathjax/3.2.2/es5/tex-mml-chtml.js","integrity":"sha256-MASABpB4tYktI2Oitl4t+78w/lyA+D7b/s9GEP0JOGI="}}</script>
<script src="/js/third-party/math/mathjax.js"></script>


 
        <div id="click-show-text"
            data-mobile = false
            data-text = 富强,民主,文明,和谐,自由,平等,公正,法制,爱国,敬业,诚信,友善
            data-fontsize = 15px
            data-random= false>
        </div>
       

      
        <script async src=https://cdn.jsdelivr.net/npm/hexo-next-mouse-effect@latest/click/showText.js></script>
      

      
    




    <script async src="/js/fancybox_param.js"></script>





<!-- APlayer本体 -->



</body>
</html>
